- <%= t("welcome.debates.title") %>
- <%= t("welcome.debates.description") %>
-
- <%= t("welcome.proposal.title") %>
- <%= t("welcome.proposal.description") %>
-
- <%= t("welcome.decide.title") %>
- <%= t("welcome.decide.description") %>
-
- <%= t("welcome.do.title") %>
- <%= t("welcome.do.description") %>
-
<%= t("welcome.debates.title") %>
+<%= t("welcome.debates.description") %>
+<%= t("welcome.proposal.title") %>
+<%= t("welcome.proposal.description") %>
+<%= t("welcome.decide.title") %>
+<%= t("welcome.decide.description") %>
+<%= t("welcome.do.title") %>
+<%= t("welcome.do.description") %>
+No hace falta que gastes todo el dinero disponible." - zero: "Todavía no has votado ninguna propuesta de inversión." + zero: Todavía no has votado ninguna propuesta de inversión. reasons_for_not_balloting: not_logged_in: Necesitas %{signin} o %{signup} para continuar. not_verified: Las propuestas de inversión sólo pueden ser apoyadas por usuarios verificados, %{verify_account}. @@ -51,16 +51,19 @@ es: help_text_4: "Para conseguir el mayor número de apoyos y votos posible, elige un titular descriptivo y comprensible de tu proyecto. Después tienes un espacio para desarrollar el planteamiento de tu propuesta. Aporta todos los datos y explicaciones, e incluso documentos e imágenes, para ayudar a otras personas participantes a entender mejor lo que planteas." investments: form: - tags_instructions: "Etiqueta esta propuesta. Puedes elegir entre las categorías propuestas o introducir las que desees" - tags_label: Temas tag_category_label: "Categorías" + tags_instructions: "Etiqueta esta propuesta. Puedes elegir entre las categorías propuestas o introducir las que desees" + tags_label: Etiquetas tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')" + map_location: "Ubicación en el mapa" + map_location_instructions: "Navega por el mapa hasta la ubicación y coloca el marcador." + map_remove_marker: "Eliminar el marcador" index: title: Presupuestos participativos unfeasible: Propuestas de inversión no viables - unfeasible_text: Las propuestas presentadas deben cumplir una serie de criterios (legalidad, concreción, ser competencia del Ayuntamiento, no superar el tope del presupuesto; %{definitions}) para ser declaradas viables y llegar hasta la fase de votación final. Todas las propuestas que no cumplen estos criterios son marcadas como inviables y publicadas en la siguiente lista, junto con su informe de inviabilidad. + unfeasible_text: "Las propuestas presentadas deben cumplir una serie de criterios (legalidad, concreción, ser competencia del Ayuntamiento, no superar el tope del presupuesto; %{definitions}) para ser declaradas viables y llegar hasta la fase de votación final. Todas las propuestas que no cumplen estos criterios son marcadas como inviables y publicadas en la siguiente lista, junto con su informe de inviabilidad." unfeasible_text_definitions: ver definiciones aquí - by_heading: "Propuestas de inversión con ámbito: %{heading}" + by_heading: 'Propuestas de inversión con ámbito: %{heading}' search_form: button: Buscar placeholder: Buscar propuestas de inversión... @@ -75,10 +78,10 @@ es: other: "Has votado %{count} propuestas por un valor de %{amount_spent}" voted_info: Puedes %{link} en cualquier momento hasta el cierre de esta fase. No hace falta que gastes todo el dinero disponible. voted_info_link: cambiar tus votos - different_heading_assigned_html: "Ya apoyaste propuestas de otra sección del presupuesto: %{heading_link}" + different_heading_assigned_html: 'Ya apoyaste propuestas de otra sección del presupuesto: %{heading_link}' change_ballot: "Si cambias de opinión puedes borrar tus votos en %{check_ballot} y volver a empezar." check_ballot_link: "revisar mis votos" - zero: "Todavía no has votado ninguna propuesta de inversión en este ámbito del presupuesto." + zero: Todavía no has votado ninguna propuesta de inversión en este ámbito del presupuesto. verified_only: "Para crear una nueva propuesta de inversión %{verify}." verify_account: "verifica tu cuenta" create: "Crear propuesta de inversión" @@ -111,22 +114,22 @@ es: wrong_price_format: Solo puede incluir caracteres numéricos investment: add: Votar - already_added: "Ya has añadido esta propuesta de inversión" + already_added: Ya has añadido esta propuesta de inversión already_supported: Ya has apoyado esta propuesta. ¡Compártelo! support_title: Apoyar esta propuesta confirm_group: "Sólo puedes apoyar propuestas en un distrito. Si sigues adelante no podrás cambiar esta decisión. ¿Estás seguro?" supports: + zero: Sin apoyos one: 1 apoyo other: "%{count} apoyos" - zero: Sin apoyos give_support: Apoyar header: check_ballot: Revisar mis votos - different_heading_assigned_html: "Ya apoyaste propuestas de otra sección del presupuesto: %{heading_link}" + different_heading_assigned_html: 'Ya apoyaste propuestas de otra sección del presupuesto: %{heading_link}' change_ballot: "Si cambias de opinión puedes borrar tus votos en %{check_ballot} y volver a empezar." check_ballot_link: "revisar mis votos" progress_bar: - available: "Disponible: " + available: 'Disponible: ' show: group: Grupo phase: Fase actual @@ -144,8 +147,8 @@ es: ballot_lines_count: Votos hide_discarded_link: Ocultar descartadas show_all_link: Mostrar todas - price: Coste + price: Coste total amount_available: Presupuesto disponible - accepted: "Propuesta de inversión aceptada: " - discarded: "Propuesta de inversión descartada: " + accepted: 'Propuesta de inversión aceptada: ' + discarded: 'Propuesta de inversión descartada: ' incompatibles: Incompatibles diff --git a/config/locales/es/community.yml b/config/locales/es/community.yml index f0f61b037..ccb8f3cfa 100644 --- a/config/locales/es/community.yml +++ b/config/locales/es/community.yml @@ -28,9 +28,9 @@ es: edit: Editar tema destroy: Eliminar tema comments: + zero: Sin comentarios one: 1 Comentario other: "%{count} Comentarios" - zero: Sin comentarios author: Autor back: Volver a %{community} %{proposal} topic: diff --git a/config/locales/es/devise.yml b/config/locales/es/devise.yml index 6ede31f7d..103b33243 100644 --- a/config/locales/es/devise.yml +++ b/config/locales/es/devise.yml @@ -37,11 +37,7 @@ es: updated: "Tu contraseña ha cambiado correctamente. Has sido identificado correctamente." updated_not_active: "Tu contraseña se ha cambiado correctamente." registrations: - destroyed: - "¡Adiós! Tu cuenta ha sido cancelada. Esperamos volver a verte pronto. Le informamos que de conformidad con su petición, - sus datos personales registrados como usuario de la Web y que forman parte del fichero 'Fichero' - cuyo responsable es 'Responsable', han sido cancelados en los términos de lo previsto en el artículo 16 de la - Ley Orgánica 15/1999 de Protección de Datos de Carácter Personal y del artículo 31 de su Reglamento de desarrollo (RD 1720/2007)." + destroyed: "¡Adiós! Tu cuenta ha sido cancelada. Esperamos volver a verte pronto. Le informamos que de conformidad con su petición, sus datos personales registrados como usuario de la Web y que forman parte del fichero 'Fichero' cuyo responsable es 'Responsable', han sido cancelados en los términos de lo previsto en el artículo 16 de la Ley Orgánica 15/1999 de Protección de Datos de Carácter Personal y del artículo 31 de su Reglamento de desarrollo (RD 1720/2007)." signed_up: "¡Bienvenido! Has sido identificado." signed_up_but_inactive: "Te has registrado correctamente, pero no has podido iniciar sesión porque tu cuenta no ha sido activada." signed_up_but_locked: "Te has registrado correctamente, pero no has podido iniciar sesión porque tu cuenta está bloqueada." diff --git a/config/locales/es/devise_views.yml b/config/locales/es/devise_views.yml index 184454654..aee940d5f 100644 --- a/config/locales/es/devise_views.yml +++ b/config/locales/es/devise_views.yml @@ -1,4 +1,3 @@ ---- es: devise_views: confirmations: @@ -42,8 +41,8 @@ es: new: email_label: Email organization_name_label: Nombre de la organización - password_confirmation_label: Confirmar contraseña - password_label: Contraseña + password_confirmation_label: Repite la contraseña anterior + password_label: Contraseña que utilizarás para acceder a este sitio web phone_number_label: Teléfono responsible_name_label: Nombre y apellidos de la persona responsable del colectivo responsible_name_note: Será la persona representante de la asociación/colectivo en cuyo nombre se presenten las propuestas @@ -51,7 +50,7 @@ es: title: Registrarse como organización / colectivo success: back_to_index: Entendido, volver a la página principal - instructions_1_html: En breve nos pondremos en contacto contigo para verificar que realmente representas a este colectivo. + instructions_1_html: "En breve nos pondremos en contacto contigo para verificar que realmente representas a este colectivo." instructions_2_html: Mientras revisa tu correo electrónico, te hemos enviado un enlace para confirmar tu cuenta. instructions_3_html: Una vez confirmado, podrás empezar a participar como colectivo no verificado. thank_you_html: Gracias por registrar tu colectivo en la web. Ahora está pendiente de verificación. @@ -65,22 +64,22 @@ es: new: email_label: Email send_submit: Recibir instrucciones - title: "¿Has olvidado tu contraseña?" + title: '¿Has olvidado tu contraseña?' sessions: new: login_label: Email o nombre de usuario - password_label: Contraseña + password_label: Contraseña que utilizarás para acceder a este sitio web remember_me: Recordarme submit: Entrar - title: Entrar + title: Iniciar sesión shared: links: login: Entrar - new_confirmation: "¿No has recibido instrucciones para confirmar tu cuenta?" - new_password: "¿Olvidaste tu contraseña?" - new_unlock: "¿No has recibido instrucciones para desbloquear?" + new_confirmation: '¿No has recibido instrucciones para confirmar tu cuenta?' + new_password: '¿Olvidaste tu contraseña?' + new_unlock: '¿No has recibido instrucciones para desbloquear?' signin_with_provider: Entrar con %{provider} - signup: "¿No tienes una cuenta? %{signup_link}" + signup: '¿No tienes una cuenta? %{signup_link}' signup_link: Regístrate unlocks: new: @@ -91,13 +90,13 @@ es: registrations: delete_form: erase_reason_label: Razón de la baja - info: Esta acción no se puede deshacer. Una vez que des de baja tu cuenta, no podrás volver a hacer login con ella. - info_reason: Si quieres, escribe el motivo por el que te das de baja (opcional). - submit: Borrar mi cuenta + info: Esta acción no se puede deshacer. Una vez que des de baja tu cuenta, no podrás volver a entrar con ella. + info_reason: Si quieres, escribe el motivo por el que te das de baja (opcional) + submit: Darme de baja title: Darme de baja edit: current_password_label: Contraseña actual - edit: Editar + edit: Editar propuesta email_label: Email leave_blank: Dejar en blanco si no deseas cambiarla need_current: Necesitamos tu contraseña actual para confirmar los cambios @@ -108,7 +107,7 @@ es: new: cancel: Cancelar login email_label: Tu correo electrónico - organization_signup: "¿Representas a una organización / colectivo? %{signup_link}" + organization_signup: '¿Representas a una organización / colectivo? %{signup_link}' organization_signup_link: Regístrate aquí password_confirmation_label: Repite la contraseña anterior password_label: Contraseña que utilizarás para acceder a este sitio web @@ -118,8 +117,8 @@ es: terms_link: condiciones de uso terms_title: Al registrarte aceptas las condiciones de uso title: Registrarse - username_is_available: "Nombre de usuario disponible" - username_is_not_available: "Nombre de usuario ya existente" + username_is_available: Nombre de usuario disponible + username_is_not_available: Nombre de usuario ya existente username_label: Nombre de usuario username_note: Nombre público que aparecerá en tus publicaciones success: diff --git a/config/locales/es/documents.yml b/config/locales/es/documents.yml index a0b646ecc..bd3866137 100644 --- a/config/locales/es/documents.yml +++ b/config/locales/es/documents.yml @@ -2,33 +2,23 @@ es: documents: tab: Documentos no_documents: No hay documentos subidos - upload_document: Subir documento - max_documents_allowed_reached_html: ¡Has alcanzado el número máximo de documentos permitidos! Tienes que eliminar uno antes de poder subir otro. + max_documents_allowed_reached_html: '¡Has alcanzado el número máximo de documentos permitidos! Tienes que eliminar uno antes de poder subir otro.' form: title: Documentos + title_placeholder: Añade un título descriptivo para el documento attachment_label: Selecciona un documento - submit_button: Subir documento delete_button: Eliminar documento - note: "Puedes subir hasta un máximo de %{max_documents_allowed} documentos en los formatos: %{accepted_content_types}, y de hasta %{max_file_size} MB por archivo." + note: 'Puedes subir hasta un máximo de %{max_documents_allowed} documentos en los formatos: %{accepted_content_types}, y de hasta %{max_file_size} MB por archivo.' add_new_document: Añadir nuevo documento - new: - title: Subir un documento - recommendations_title: Consejos para subir archivos - recommendation_one_html: Puedes subir hasta un máximo de %{max_documents_allowed} documentos - recommendation_two_html: Sólo puedes subir archivos %{accepted_content_types}. - recommendation_three_html: Puedes subir archivos de hasta %{max_file_size} MB actions: - create: - notice: "El documento se ha creado correctamente." - alert: "El documento no se ha podido crear. Revise los errores del formulario." destroy: - notice: "El documento se ha eliminado correctamente." - alert: "El documento no se ha podido eliminar." - confirm: "¿Está seguro de que desea eliminar el documento? Esta acción no se puede deshacer!" + notice: El documento se ha eliminado correctamente. + alert: El documento no se ha podido eliminar. + confirm: '¿Está seguro de que desea eliminar el documento? Esta acción no se puede deshacer!' buttons: download_document: Descargar archivo destroy_document: Eliminar errors: messages: in_between: debe estar entre %{min} y %{max} - wrong_content_type: El tipo de contenido %{content_type} del archivo no coincide con ninguno de los tipos de contenido aceptados %{accepted_content_types} + wrong_content_type: El tipo de contenido %{content_type} del archivo no coincide con ninguno de los tipos de contenido aceptados %{accepted_content_types} \ No newline at end of file diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index 9f52ccc38..0d0b4b849 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -1,4 +1,3 @@ ---- es: account: show: @@ -14,8 +13,8 @@ es: phone_number_label: Teléfono public_activity_label: Mostrar públicamente mi lista de actividades public_interests_label: Mostrar públicamente mis intereses - public_interests_my_title_list: Lista de intereses (Etiquetas de los elementos que sigues) - public_interests_user_title_list: Lista de intereses (Etiquetas de los elementos seguidos este usuario) + public_interests_my_title_list: Lista de intereses (etiquetas de los elementos que sigues) + public_interests_user_title_list: Lista de intereses (etiquetas de los elementos seguidos este usuario) public_interests_my_empty_list: Aún no sigues ningún elemento. public_interests_user_empty_list: Este usuario no sigue ningún elemento todavía. save_changes_submit: Guardar cambios @@ -48,14 +47,14 @@ es: deleted: Este comentario ha sido eliminado moderator: Moderador responses: + zero: Sin respuestas one: 1 Respuesta other: "%{count} Respuestas" - zero: Sin respuestas user_deleted: Usuario eliminado votes: + zero: Sin votos one: 1 voto other: "%{count} votos" - zero: Sin votos form: comment_as_admin: Comentar como administrador comment_as_moderator: Comentar como moderador @@ -80,13 +79,13 @@ es: submit_button: Empieza un debate debate: comments: + zero: Sin comentarios one: 1 Comentario other: "%{count} Comentarios" - zero: Sin comentarios votes: + zero: Sin votos one: 1 voto other: "%{count} votos" - zero: Sin votos edit: editing: Editar debate form: @@ -99,7 +98,7 @@ es: tags_label: Temas tags_placeholder: "Escribe las etiquetas que desees separadas por coma (',')" index: - featured_debates: Destacados + featured_debates: Destacar filter_topic: one: " con el tema '%{topic}'" other: " con el tema '%{topic}'" @@ -109,6 +108,10 @@ es: hot_score: Más activos hoy most_commented: Más comentados relevance: Más relevantes + recommendations: Recomendaciones + recommendations: + without_results: No existen debates relacionados con tus intereses + without_interests: Sigue propuestas para que podamos darte recomendaciones search_form: button: Buscar placeholder: Buscar debates... @@ -146,20 +149,21 @@ es: show: author_deleted: Usuario eliminado comments: + zero: Sin comentarios one: 1 Comentario other: "%{count} Comentarios" - zero: Sin comentarios comments_title: Comentarios edit_debate_link: Editar debate flag: Este debate ha sido marcado como inapropiado por varios usuarios. login_to_comment: Necesitas %{signin} o %{signup} para comentar. share: Compartir + author: Autor update: form: submit_button: Guardar cambios errors: messages: - user_not_found: No se encontró el usuario + user_not_found: Usuario no encontrado invalid_date_range: "El rango de fechas no es válido" form: accept_terms: Acepto la %{policy} y las %{conditions} @@ -176,11 +180,13 @@ es: spending_proposal: la propuesta de gasto budget/investment: la propuesta de inversión poll/shift: el turno + poll/question/answer: la respuesta user: la cuenta verification/sms: el teléfono signature_sheet: la hoja de firmas document: el documento topic: Tema + image: Imagen geozones: none: Toda la ciudad all: Todos los ámbitos de actuación @@ -194,34 +200,34 @@ es: accessibility: Accesibilidad conditions: Condiciones de uso consul: aplicación CONSUL - consul_url: https://github.com/consul/consul + consul_url: 'https://github.com/consul/consul' contact_us: Para asistencia técnica entra en copyright: CONSUL, %{year} description: Este portal usa la %{consul} que es %{open_source}. faq: Asistencia técnica open_data_text: Todos los datos del Ayuntamiento son tuyos. open_data_title: Datos Abiertos - open_source: software libre - open_source_url: http://www.gnu.org/licenses/agpl-3.0.html + open_source: software de código abierto + open_source_url: 'http://www.gnu.org/licenses/agpl-3.0.html' participation_text: Decide cómo debe ser la ciudad que quieres. participation_title: Participación privacy: Política de privacidad transparency_text: Obtén cualquier información sobre la ciudad. transparency_title: Transparencia - transparency_url: https://transparency.consul + transparency_url: 'https://transparency.consul' header: administration_menu: Admin - administration: Administrar + administration: Administración available_locales: Idiomas disponibles collaborative_legislation: Procesos legislativos debates: Debates external_link_blog: Blog external_link_opendata: Datos abiertos - external_link_opendata_url: https://opendata.consul + external_link_opendata_url: 'https://opendata.consul' external_link_transparency: Transparencia - external_link_transparency_url: https://transparency.consul + external_link_transparency_url: 'https://transparency.consul' locale: 'Idioma:' - logo: CONSUL logo + logo: Logo de CONSUL management: Gestión moderation: Moderar valuation: Evaluación @@ -233,7 +239,7 @@ es: new_notifications: one: Tienes una nueva notificación other: Tienes %{count} notificaciones nuevas - no_notifications: No tienes notificaciones nuevas + no_notifications: "No tienes notificaciones nuevas" open: abierto open_city_slogan_html: Existen ciudades gobernadas directamente por sus habitantes, que debaten sobre temas que les preocupan, proponen ideas para mejorar sus vidas y deciden entre todas y todos las que se llevan a cabo. open_city_title: La ciudad que quieres será la ciudad que quieras @@ -241,7 +247,7 @@ es: proposals: Propuestas poll_questions: Votaciones budgets: Presupuestos participativos - spending_proposals: "Propuestas de inversión" + spending_proposals: Propuestas de inversión admin: watch_form_message: 'Has realizado cambios que no han sido guardados. ¿Seguro que quieres abandonar la página?' legacy_legislation: @@ -250,7 +256,7 @@ es: text: Para comentar este documento debes %{sign_in} o %{sign_up}. Después selecciona el texto que quieres comentar y pulsa en el botón con el lápiz. text_sign_in: iniciar sesión text_sign_up: registrarte - title: "¿Cómo puedo comentar este documento?" + title: '¿Cómo puedo comentar este documento?' locale: Español notifications: index: @@ -269,7 +275,7 @@ es: map: title: "Distritos" proposal_for_district: "Crea una propuesta para tu distrito" - select_district: "Ámbito de actuación" + select_district: Ámbito de actuación start_proposal: Crea una propuesta omniauth: facebook: @@ -277,7 +283,8 @@ es: sign_up: Regístrate con Facebook name: Facebook finish_signup: - title: Añade tu email + title: "Detalles adicionales de tu cuenta" + username_warning: "Debido a que hemos cambiado la forma en la que nos conectamos con redes sociales y es posible que tu nombre de usuario aparezca como 'ya en uso', incluso si antes podías acceder con él. Si es tu caso, por favor elige un nombre de usuario distinto." google_oauth2: sign_in: Entra con Google sign_up: Regístrate con Google @@ -289,9 +296,6 @@ es: info_sign_in: "Entra con:" info_sign_up: "Regístrate con:" or_fill: "O rellena el siguiente formulario:" - finish_signup: - title: "Detalles adicionales de tu cuenta" - username_warning: "Debido a que hemos cambiado la forma en la que nos conectamos con redes sociales y es posible que tu nombre de usuario aparezca como 'ya en uso', incluso si antes podías acceder con él. Si es tu caso, por favor elige un nombre de usuario distinto." proposals: create: form: @@ -316,7 +320,7 @@ es: done: Realizada other: Otra form: - geozone: "Ámbito de actuación" + geozone: Ámbito de actuación proposal_external_url: Enlace a documentación adicional proposal_question: Pregunta de la propuesta proposal_question_example_html: "Debe ser resumida en una pregunta cuya respuesta sea Sí o No.
Ej. '¿Está usted de acuerdo en peatonalizar la calle Mayor?'" @@ -328,10 +332,13 @@ es: proposal_title: Título de la propuesta proposal_video_url: Enlace a vídeo externo proposal_video_url_note: Puedes añadir un enlace a YouTube o Vimeo + tag_category_label: "Categorías" tags_instructions: "Etiqueta esta propuesta. Puedes elegir entre las categorías propuestas o introducir las que desees" tags_label: Temas - tag_category_label: "Categorías" tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')" + map_location: "Ubicación en el mapa" + map_location_instructions: "Navega por el mapa hasta la ubicación y coloca el marcador." + map_remove_marker: "Eliminar el marcador" index: featured_proposals: Destacadas filter_topic: @@ -344,6 +351,10 @@ es: most_commented: Más comentadas relevance: Más relevantes archival_date: Archivadas + recommendations: Recomendaciones + recommendations: + without_results: No existen propuestas relacionadas con tus intereses + without_interests: Sigue propuestas para que podamos darte recomendaciones retired_proposals: Propuestas retiradas retired_proposals_link: "Propuestas retiradas por sus autores" retired_links: @@ -361,7 +372,7 @@ es: one: " que contiene '%{search_term}'" other: " que contienen '%{search_term}'" select_order: Ordenar por - select_order_long: Estas viendo las propuestas + select_order_long: 'Estas viendo las propuestas' start_proposal: Crea una propuesta title: Propuestas ciudadanas top: Top semanal @@ -379,7 +390,7 @@ es: new: form: submit_button: Crear propuesta - more_info: "¿Cómo funcionan las propuestas ciudadanas?" + more_info: '¿Cómo funcionan las propuestas ciudadanas?' recommendation_one: No escribas el título de la propuesta o frases enteras en mayúsculas. En internet eso se considera gritar. Y a nadie le gusta que le griten. recommendation_three: Disfruta de este espacio, de las voces que lo llenan, también es tuyo. recommendation_two: Cualquier propuesta o comentario que implique una acción ilegal será eliminada, también las que tengan la intención de sabotear los espacios de propuesta, todo lo demás está permitido. @@ -390,23 +401,27 @@ es: proposal: created: "¡Has creado una propuesta!" share: - guide: "Compártela para que la gente empieze a apoyarla." + guide: "Compártela para que la gente empiece a apoyarla." edit: "Antes de que se publique podrás modificar el texto a tu gusto." - view_proposal: "Ahora no, ir a mi propuesta" + view_proposal: Ahora no, ir a mi propuesta improve_info: "Mejora tu campaña y consigue más apoyos" improve_info_link: "Ver más información" - already_supported: "¡Ya has apoyado esta propuesta, compártela!" + already_supported: '¡Ya has apoyado esta propuesta, compártela!' comments: + zero: Sin comentarios one: 1 Comentario other: "%{count} Comentarios" - zero: Sin comentarios reason_for_supports_necessary: 1% del Censo support: Apoyar support_title: Apoyar esta propuesta supports: + zero: Sin apoyos one: 1 apoyo other: "%{count} apoyos" - zero: Sin apoyos + votes: + zero: Sin votos + one: 1 voto + other: "%{count} votos" supports_necessary: "%{number} apoyos necesarios" total_percent: 100% archived: "Esta propuesta ha sido archivada y ya no puede recoger apoyos." @@ -416,9 +431,9 @@ es: author_deleted: Usuario eliminado code: 'Código de la propuesta:' comments: + zero: Sin comentarios one: 1 Comentario other: "%{count} Comentarios" - zero: Sin comentarios comments_tab: Comentarios edit_proposal_link: Editar propuesta flag: Esta propuesta ha sido marcada como inapropiada por varios usuarios. @@ -427,8 +442,8 @@ es: retired_warning: "El autor de esta propuesta considera que ya no debe seguir recogiendo apoyos." retired_warning_link_to_explanation: Revisa su explicación antes de apoyarla. retired: Propuesta retirada por el autor - send_notification: Enviar notificación share: Compartir + send_notification: Enviar notificación no_notifications: "Esta propuesta no tiene notificaciones." embed_video_title: "Vídeo en %{proposal}" title_external_url: "Documentación adicional" @@ -453,11 +468,7 @@ es: participate_button_expired: "Votación terminada" no_geozone_restricted: "Toda la ciudad" geozone_restricted: "Distritos" - geozone_info: "Pueden participar las personas empadronadas en: " - can_answer: "¡Puedes participar en esta votación!" - cant_answer: "Esta votación no está disponible en tu zona" - cant_answer_not_logged_in: "Necesitas iniciar sesión o registrarte para participar" - cant_answer_verify: "Por favor verifica tu cuenta para poder responder" + geozone_info: 'Pueden participar las personas empadronadas en: ' already_answer: "Ya has participado en esta votación" section_header: icon_alt: Icono de Votaciones @@ -469,24 +480,12 @@ es: help_text_1: "Las votaciones se convocan cuando una propuesta ciudadana alcanza el 1% de apoyos del censo con derecho a voto. En las votaciones también se pueden incluir cuestiones que el Ayuntamiento somete a decisión directa de la ciudadanía." help_text_2: "Para participar en la próxima votación tienes que registrarte en %{org} y verificar tu cuenta. Pueden votar todas las personas empadronadas en la ciudad mayores de 16 años. Los resultados de todas las votaciones serán vinculantes para el gobierno." show: - dates_title: "Fechas de participación" + already_voted_in_booth: "Ya has participado en esta votación en urnas presenciales, no puedes volver a participar." + already_voted_in_web: "Ya has participado en esta votación. Si vuelves a votar se sobreescribirá tu resultado anterior." + back: Volver a votaciones cant_answer_not_logged_in: "Necesitas %{signin} o %{signup} para participar." - signin: iniciar sesión - signup: registrarte - cant_answer_verify_html: "Por favor %{verify_link} para poder responder." - verify_link: "verifica tu cuenta" - cant_answer_incoming: "Esta votación todavía no ha comenzado." - cant_answer_expired: "Esta votación ha terminado." - poll_questions: - create_question: "Crear pregunta para votación" - default_valid_answers: "Sí, No" - show: - answer_this_question: "Responder a esta pregunta" - original_proposal: "Propuesta original" - author: "Creado por" - dates_title: "Fechas de participación" - more_info: "Más información" - not_logged_in: "Necesitas %{signin} o %{signup} para participar." + comments_tab: Comentarios + login_to_comment: Necesitas %{signin} o %{signup} para comentar. signin: iniciar sesión signup: registrarte cant_answer_verify_html: "Por favor %{verify_link} para poder responder." @@ -494,9 +493,36 @@ es: cant_answer_incoming: "Esta votación todavía no ha comenzado." cant_answer_expired: "Esta votación ha terminado." cant_answer_wrong_geozone: "Esta votación no está disponible en tu zona." + more_info_title: "Más información" + documents: Documentación + zoom_plus: Ampliar imagen + read_more: "Leer más sobre %{answer}" + read_less: "Leer menos sobre %{answer}" + participate_in_other_polls: Participar en otras votaciones + videos: "Vídeo externo" + info_menu: "Información" + stats_menu: "Estadísticas de participación" + results_menu: "Resultados de la votación" + stats: + title: "Datos de participación" + total_participation: "Participación total" + total_votes: "Nº total de votos emitidos" + votes: "VOTOS" + web: "WEB" + booth: "URNAS" + total: "TOTAL" + valid: "Válidos" + white: "En blanco" + null_votes: "Nulos" + results: + title: "Preguntas" + most_voted_answer: 'Respuesta más votada: ' + poll_questions: + create_question: "Crear pregunta" + show: vote_answer: "Votar %{answer}" voted: "Has votado %{answer}" - poll: "Votación" + voted_token: "Puedes apuntar este identificador de voto, para comprobar tu votación en el resultado final:" proposal_notifications: new: title: "Enviar mensaje" @@ -510,13 +536,10 @@ es: shared: edit: 'Editar' save: 'Guardar' - delete: 'Borrar' - comments: - title: 'Comentarios' - login_to_comment: 'Necesitas %{signin} o %{signup} para comentar.' - "yes": "Sí" + delete: Borrar + "yes": "Si" "no": "No" - search_results: "Resultados de búsqueda" + search_results: "Resultados de la búsqueda" advanced_search: author_type: 'Por categoría de autor' author_type_blank: 'Elige una categoría' @@ -534,7 +557,6 @@ es: search: 'Filtrar' title: 'Búsqueda avanzada' to: 'Hasta' - delete: 'Borrar' author_info: author_deleted: Usuario eliminado back: Volver @@ -552,10 +574,10 @@ es: destroy: notice_html: "¡Has dejado de seguir este proyecto de inverisión! Ya no recibirás más notificaciones relacionadas con este proyecto." proposal: - create: - notice_html: "¡Ahora estás siguiendo esta propuesta ciudadana! Te notificaremos los cambios a medida que se produzcan para que estés al día." - destroy: - notice_html: "¡Has dejado de seguir esta propuesta ciudadana! Ya no recibirás más notificaciones relacionadas con esta propuesta." + create: + notice_html: "¡Ahora estás siguiendo esta propuesta ciudadana! Te notificaremos los cambios a medida que se produzcan para que estés al día." + destroy: + notice_html: "¡Has dejado de seguir esta propuesta ciudadana! Ya no recibirás más notificaciones relacionadas con esta propuesta." hide: Ocultar print: print_button: Imprimir esta información @@ -588,12 +610,16 @@ es: target_blank_html: " (se abre en ventana nueva)" you_are_in: "Estás en" unflag: Deshacer denuncia - unfollow: Dejar de seguir + unfollow: "Dejar de seguir" unfollow_entity: "Dejar de seguir %{entity}" outline: budget: Presupuestos participativos searcher: Buscador go_to_page: "Ir a la página de " + share: Compartir + orbit: + previous_slide: Imagen anterior + next_slide: Siguiente imagen social: blog: "Blog de %{org}" facebook: "Facebook de %{org}" @@ -608,7 +634,7 @@ es: association_name: 'Nombre de la asociación' description: Descripción detallada external_url: Enlace a documentación adicional - geozone: "Ámbito de actuación" + geozone: Ámbito de actuación submit_buttons: create: Crear new: Crear @@ -616,7 +642,7 @@ es: index: title: Presupuestos participativos unfeasible: Propuestas de inversión no viables - by_geozone: "Propuestas de inversión con ámbito: %{geozone}" + by_geozone: 'Propuestas de inversión con ámbito: %{geozone}' search_form: button: Buscar placeholder: Propuestas de inversión... @@ -630,7 +656,7 @@ es: unfeasible: No viables start_spending_proposal: Crea una propuesta de inversión new: - more_info: "¿Cómo funcionan los presupuestos participativos?" + more_info: '¿Cómo funcionan los presupuestos participativos?' recommendation_one: Es fundamental que haga referencia a una actuación presupuestable. recommendation_three: Intenta detallar lo máximo posible la propuesta para que el equipo de gobierno encargado de estudiarla tenga las menor dudas posibles. recommendation_two: Cualquier propuesta o comentario que implique acciones ilegales será eliminada. @@ -647,9 +673,9 @@ es: support: Apoyar support_title: Apoyar este proyecto supports: + zero: Sin apoyos one: 1 apoyo other: "%{count} apoyos" - zero: Sin apoyos stats: index: visits: Visitas @@ -669,11 +695,11 @@ es: users: direct_messages: new: - body_label: "Mensaje" + body_label: Mensaje direct_messages_bloqued: "Este usuario ha decidido no recibir mensajes privados" - submit_button: "Enviar mensaje" + submit_button: Enviar mensaje title: Enviar mensaje privado a %{receiver} - title_label: "Título" + title_label: Título verified_only: Para enviar un mensaje privado %{verify_account} verify_account: verifica tu cuenta authenticate: Necesitas %{signin} o %{signup}. @@ -686,6 +712,11 @@ es: deleted_debate: Este debate ha sido eliminado deleted_proposal: Esta propuesta ha sido eliminada deleted_budget_investment: Esta propuesta de inversión ha sido eliminada + proposals: Propuestas + debates: Debates + budget_investments: Proyectos de presupuestos participativos + comments: Comentarios + actions: Acciones filters: comments: one: 1 Comentario @@ -704,7 +735,7 @@ es: other: "%{count} Siguiendo" no_activity: Usuario sin actividad pública no_private_messages: "Este usuario no acepta mensajes privados." - private_activity: Este usuario ha decidido mantener en privado su lista de actividades + private_activity: Este usuario ha decidido mantener en privado su lista de actividades. send_private_message: "Enviar un mensaje privado" proposals: send_notification: "Enviar notificación" @@ -749,10 +780,20 @@ es: proposal: description: Espacio abierto para propuestas ciudadanas sobre el tipo de ciudad en el que queremos vivir. title: Propones + recommended: + title: Recomendaciones que te pueden interesar + debates: + title: Debates recomendados + btn_text_link: Todos los debates recomendados + proposals: + title: Propuestas recomendadas + btn_text_link: Todas las propuestas recomendadas + budget_investments: + title: Presupuestos recomendados verification: i_dont_have_an_account: No tengo cuenta, quiero crear una y verificarla i_have_an_account: Ya tengo una cuenta que quiero verificar - question: ¿Tienes ya una cuenta en %{org_name}? + question: '¿Tienes ya una cuenta en %{org_name}?' title: Verificación de cuenta welcome: go_to_index: Ahora no, ver propuestas diff --git a/config/locales/es/images.yml b/config/locales/es/images.yml new file mode 100644 index 000000000..f18d9636f --- /dev/null +++ b/config/locales/es/images.yml @@ -0,0 +1,21 @@ +es: + images: + remove_image: Eliminar imagen + form: + title: Imagen descriptiva + title_placeholder: Añade un título descriptivo para la imagen + attachment_label: Selecciona una imagen + delete_button: Eliminar imagen + note: 'Puedes subir una imagen en los formatos: %{accepted_content_types}, y de hasta %{max_file_size} MB por archivo.' + add_new_image: Añadir imagen + admin_title: "Imagen principal de la votación" + admin_alt_text: "Texto alternativo para la imagen" + actions: + destroy: + notice: La imagen se ha eliminado correctamente. + alert: La imagen no se ha podido eliminar. + confirm: '¿Está seguro de que desea eliminar la imagen? Esta acción no se puede deshacer!' + errors: + messages: + in_between: debe estar entre %{min} y %{max} + wrong_content_type: El tipo de contenido %{content_type} de la imagen no coincide con ninguno de los tipos de contenido aceptados %{accepted_content_types} diff --git a/config/locales/es/kaminari.yml b/config/locales/es/kaminari.yml index 7cf5bf57e..81c74af68 100644 --- a/config/locales/es/kaminari.yml +++ b/config/locales/es/kaminari.yml @@ -1,23 +1,22 @@ ---- es: helpers: page_entries_info: entry: + zero: Entradas one: entrada other: entradas - zero: entradas more_pages: display_entries: Mostrando %{first} - %{last} de un total de %{total} %{entry_name} one_page: display_entries: + zero: "No se han encontrado %{entry_name}" one: Hay 1 %{entry_name} other: Hay %{count} %{entry_name} - zero: No se han encontrado %{entry_name} views: pagination: + current: Estás en la página first: Primera last: Última next: Siguiente previous: Anterior truncate: "…" - current: Estás en la página diff --git a/config/locales/es/legislation.yml b/config/locales/es/legislation.yml index 4d2a72cf5..e2a6a63a6 100644 --- a/config/locales/es/legislation.yml +++ b/config/locales/es/legislation.yml @@ -1,4 +1,3 @@ ---- es: legislation: annotations: @@ -20,8 +19,8 @@ es: signup: registrarte index: title: Comentarios - see_in_context: Ver en contexto comments_about: Comentarios sobre + see_in_context: Ver en contexto comments_count: one: "%{count} comentario" other: "%{count} comentarios" @@ -49,6 +48,8 @@ es: processes: header: view_process_information: Ver información del proceso + proposals: + empty_proposals: No hay propuestas debate: empty_questions: No hay preguntas participate: Realiza tus aportaciones al debate previo participando en los siguientes temas. @@ -76,7 +77,7 @@ es: phase_not_open: not_open: Esta fase del proceso todavía no está abierta phase_empty: - empty: No hay nada publicado todavía + empty: No hay nada publicado todavía process: see_latest_comments: Ver últimas aportaciones see_latest_comments_title: Aportar a este proceso @@ -86,6 +87,7 @@ es: draft_publication_date: Publicación borrador allegations_dates: Alegaciones result_publication_date: Publicación resultados + proposals_dates: Propuestas questions: comments: comment_button: Publicar respuesta @@ -117,3 +119,8 @@ es: shared: share: Compartir share_comment: Comentario sobre la %{version_name} del borrador del proceso %{process_name} + proposals: + form: + tags_label: "Categorías" + not_verified: "Para votar propuestas %{verify_account}." + closed: "Este proceso se ha cerrado y ya no puede recoger votos." diff --git a/config/locales/es/mailers.yml b/config/locales/es/mailers.yml index dc51148f8..e92774d2b 100644 --- a/config/locales/es/mailers.yml +++ b/config/locales/es/mailers.yml @@ -1,4 +1,3 @@ ---- es: mailers: no_reply: "Este mensaje se ha enviado desde una dirección de correo electrónico que no admite respuestas." @@ -23,7 +22,7 @@ es: title: Nueva respuesta a tu comentario unfeasible_spending_proposal: hi: "Estimado usuario," - new_html: "Por todo ello, te invitamos a que elabores una nueva propuesta que se ajuste a las condiciones de este proceso. Esto lo puedes hacer en este enlace: %{url}." + new_html: 'Por todo ello, te invitamos a que elabores una nueva propuesta que se ajuste a las condiciones de este proceso. Esto lo puedes hacer en este enlace: %{url}.' new_href: "nueva propuesta de inversión" reconsider_html: "Si consideras que la propuesta rechazada cumple los requisitos para mantenerla como propuesta de inversión, podrás comunicarlo, en el plazo de 48 horas, al correo example@consul.es, indicando necesariamente para su tramitación el código %{code} como asunto del correo, correspondiente a tu propuesta." sincerely: "Atentamente" @@ -31,6 +30,16 @@ es: sorry: "Sentimos las molestias ocasionadas y volvemos a darte las gracias por tu inestimable participación." subject: "Tu propuesta de inversión '%{code}' ha sido marcada como inviable" unfeasible_html: "Desde el Ayuntamiento queremos agradecer tu participación en los Presupuestos Participativos. Lamentamos informarte de que tu propuesta '%{title}' quedará excluida de este proceso participativo por el siguiente motivo:" + budget_investment_unfeasible: + hi: "Estimado usuario," + new_html: 'Por todo ello, te invitamos a que elabores un nuevo proyecto de gasto que se ajuste a las condiciones de este proceso. Esto lo puedes hacer en este enlace: %{url}.' + new_href: "nueva propuesta de inversión" + reconsider_html: "Si consideras que el proyecto rechazado cumple los requisitos para mantenerlo como proyecto de gasto, podrás comunicarlo, en el plazo de 48 horas, al correo example@consul.es, indicando necesariamente para su tramitación el código %{code} como asunto del correo, correspondiente a tu proyecto." + sincerely: "Atentamente" + signatory: "DIRECCIÓN GENERAL DE PARTICIPACIÓN CIUDADANA" + sorry: "Sentimos las molestias ocasionadas y volvemos a darte las gracias por tu inestimable participación." + subject: "Tu propuesta de inversión '%{code}' ha sido marcada como inviable" + unfeasible_html: "Desde el Ayuntamiento queremos agradecer tu participación en los Presupuestos Participativos. Lamentamos informarte de que tu proyecto '%{title}' quedará excluido de este proceso participativo por el siguiente motivo:" proposal_notification_digest: info: "A continuación te mostramos las nuevas notificaciones que han publicado los autores de las propuestas que estás apoyando en %{org_name}." title: "Notificaciones de propuestas en %{org_name}" @@ -63,16 +72,6 @@ es: sincerely: "Atentamente," signatory: "DIRECCIÓN GENERAL DE PARTICIPACIÓN CIUDADANA" share: "Comparte tu proyecto" - budget_investment_unfeasible: - hi: "Estimado usuario," - new_html: "Por todo ello, te invitamos a que elabores un nuevo proyecto de gasto que se ajuste a las condiciones de este proceso. Esto lo puedes hacer en este enlace: %{url}." - new_href: "nueva propuesta de inversión" - reconsider_html: "Si consideras que el proyecto rechazado cumple los requisitos para mantenerlo como proyecto de gasto, podrás comunicarlo, en el plazo de 48 horas, al correo example@consul.es, indicando necesariamente para su tramitación el código %{code} como asunto del correo, correspondiente a tu proyecto." - sincerely: "Atentamente" - signatory: "DIRECCIÓN GENERAL DE PARTICIPACIÓN CIUDADANA" - sorry: "Sentimos las molestias ocasionadas y volvemos a darte las gracias por tu inestimable participación." - subject: "Tu propuesta de inversión '%{code}' ha sido marcada como inviable" - unfeasible_html: "Desde el Ayuntamiento queremos agradecer tu participación en los Presupuestos Participativos. Lamentamos informarte de que tu proyecto '%{title}' quedará excluido de este proceso participativo por el siguiente motivo:" budget_investment_selected: subject: "Tu propuesta de inversión '%{code}' ha sido seleccionada" hi: "Estimado/a usuario/a" diff --git a/config/locales/es/management.yml b/config/locales/es/management.yml index 87358a438..5b889f2aa 100644 --- a/config/locales/es/management.yml +++ b/config/locales/es/management.yml @@ -1,4 +1,3 @@ ---- es: management: account: @@ -29,7 +28,7 @@ es: not_in_census_info: 'Las personas no empadronadas pueden participar en el Portal de Gobierno Abierto con las siguientes posibilidades:' please_check_account_data: Compruebe que los datos anteriores son correctos para proceder a verificar la cuenta completamente. title: Gestión de usuarios - under_age: No tienes edad suficiente para verificar tu cuenta. + under_age: "No tienes edad suficiente para verificar tu cuenta." verify: Verificar usuario email_label: Email date_of_birth: Fecha de nacimiento @@ -63,12 +62,12 @@ es: support_proposals: Apoyar propuestas vote_proposals: Participar en las votaciones finales print: - proposals_info: Haz tu propuesta en http://url.consul + proposals_info: 'Haz tu propuesta en http://url.consul' proposals_note: Las propuestas más apoyadas serán llevadas a votación. Y si las acepta una mayoría, el Ayuntamiento las llevará a cabo. proposals_title: 'Propuestas:' - spending_proposals_info: Participa en http://url.consul + spending_proposals_info: 'Participa en http://url.consul' spending_proposals_note: Los presupuestos participativos se invertirán en las propuestas de inversión más apoyadas. - budget_investments_info: Participa en http://url.consul + budget_investments_info: 'Participa en http://url.consul' budget_investments_note: Los presupuestos participativos se invertirán en las propuestas de inversión más apoyadas. print_info: Imprimir esta información proposals: @@ -99,7 +98,7 @@ es: create: Crear propuesta de inversión filters: unfeasible: Propuestas de inversión no viables - by_geozone: "Propuestas de inversión con ámbito: %{geozone}" + by_geozone: 'Propuestas de inversión con ámbito: %{geozone}' print: print_button: Imprimir search_results: @@ -115,17 +114,17 @@ es: create_user_submit: Crear usuario create_user_success_html: Hemos enviado un correo electrónico a %{email} para verificar que es suya. El correo enviado contiene un link que el usuario deberá pulsar. Entonces podrá seleccionar una clave de acceso, y entrar en la web de participación. autogenerated_password_html: "Se ha asignado la contraseña %{password} a este usuario. Puede modificarla desde el apartado 'Mi cuenta' de la web." - email_optional_label: "Email (recomendado pero opcional)" + email_optional_label: Email (recomendado pero opcional) erased_notice: Cuenta de usuario borrada. - erased_by_manager: "Borrada por el manager: %{manager}" + erased_by_manager: 'Borrada por el manager: %{manager}' erase_account_link: Borrar cuenta - erase_account_confirm: ¿Seguro que quieres borrar a este usuario? Esta acción no se puede deshacer - erase_warning: Esta acción no se puede deshacer. Por favor asegurese de que quiere eliminar esta cuenta. + erase_account_confirm: '¿Seguro que quieres borrar a este usuario? Esta acción no se puede deshacer' + erase_warning: Esta acción no se puede deshacer. Por favor asegúrese de que quiere eliminar esta cuenta. erase_submit: Borrar cuenta user_invites: new: label: Emails - info: "Introduce los emails separados por ','" + info: "Introduce los emails separados por comas (',')" submit: Enviar invitaciones title: Invitaciones para usuarios create: diff --git a/config/locales/es/moderation.yml b/config/locales/es/moderation.yml index b41ba0fbf..43fc98790 100644 --- a/config/locales/es/moderation.yml +++ b/config/locales/es/moderation.yml @@ -1,13 +1,10 @@ ---- es: moderation: - header: - title: Moderación comments: index: block_authors: Bloquear autores - confirm: "¿Estás seguro?" - filter: Filtrar + confirm: '¿Estás seguro?' + filter: Filtro filters: all: Todos pending_flag_review: Pendientes @@ -24,11 +21,11 @@ es: title: Comentarios dashboard: index: - title: Moderación + title: Moderar debates: index: block_authors: Bloquear autores - confirm: "¿Estás seguro?" + confirm: '¿Estás seguro?' filter: Filtrar filters: all: Todos @@ -44,6 +41,8 @@ es: created_at: Más nuevos flags: Más denunciados title: Debates + header: + title: Moderación menu: flagged_comments: Comentarios flagged_debates: Debates @@ -52,7 +51,7 @@ es: proposals: index: block_authors: Bloquear autores - confirm: "¿Estás seguro?" + confirm: '¿Estás seguro?' filter: Filtro filters: all: Todas diff --git a/config/locales/es/officing.yml b/config/locales/es/officing.yml index 74358ab56..6832311a7 100644 --- a/config/locales/es/officing.yml +++ b/config/locales/es/officing.yml @@ -1,4 +1,3 @@ ---- es: officing: header: @@ -8,28 +7,26 @@ es: title: Presidir mesa de votaciones info: Aquí puedes validar documentos de ciudadanos y guardar los resultados de las urnas menu: - voters: "Validar documento y votar" - total_recounts: "Recuento total y escrutinio" + voters: Validar documento y votar + total_recounts: Recuento total y escrutinio polls: final: - title: "Listado de votaciones finalizadas" - no_polls: "No tienes permiso para recuento final en ninguna votación reciente" - select_poll: "Selecciona votación" - add_results: "Añadir resultados" + title: Listado de votaciones finalizadas + no_polls: No tienes permiso para recuento final en ninguna votación reciente + select_poll: Selecciona votación + add_results: Añadir resultados results: flash: create: "Datos guardados" error_create: "Resultados NO añadidos. Error en los datos" error_wrong_booth: "Urna incorrecta. Resultados NO guardados." - error_wrong_date: "Fecha incorrecta. Resultados NO guardados." new: title: "%{poll} - Añadir resultados" not_allowed: "No tienes permiso para introducir resultados" booth: "Urna" date: "Día" select_booth: "Elige urna" - select_date: "Elige día" - ballots_white: "Papeletas en blanco" + ballots_white: "Papeletas totalmente en blanco" ballots_null: "Papeletas nulas" ballots_total: "Papeletas totales" submit: "Guardar" @@ -37,12 +34,12 @@ es: see_results: "Ver resultados" index: no_results: "No hay resultados" - results: "Resultados" + results: Resultados table_answer: Respuesta table_votes: Votos - table_whites: Papeletas en blanco - table_nulls: Papeletas nulas - table_total: Papeletas totales + table_whites: "Papeletas totalmente en blanco" + table_nulls: "Papeletas nulas" + table_total: "Papeletas totales" residence: flash: create: "Documento verificado con el Padrón" @@ -51,16 +48,19 @@ es: title: Validar documento document_number: "Número de documento (incluida letra)" submit: Validar documento - error_verifying_census: El Padrón no pudo verificar este documento. + error_verifying_census: "El Padrón no pudo verificar este documento." form_errors: evitaron verificar este documento no_assignments: "Hoy no tienes turno de presidente de mesa" voters: new: title: Votaciones table_poll: Votación - table_actions: Estado de las votaciones + table_status: Estado de las votaciones + table_actions: Acciones show: can_vote: Puede votar - error_already_voted: "Ya ha participado en esta votación." + error_already_voted: Ya ha participado en esta votación. submit: Confirmar voto success: "¡Voto introducido!" + can_vote: + submit_disable_with: "Espera, confirmando voto..." diff --git a/config/locales/es/pages.yml b/config/locales/es/pages.yml index d67568b2d..a3e0db7e0 100644 --- a/config/locales/es/pages.yml +++ b/config/locales/es/pages.yml @@ -1,4 +1,3 @@ ---- es: pages: census_terms: Para verificar la cuenta hay que tener 16 años o más y estar empadronado aportando los datos indicados anteriormente, los cuales serán contrastados. Aceptando el proceso de verificación acepta dar su consentimiento para contrastar dicha información, así como medios de contacto que figuren en dichos ficheros. Los datos aportados serán incorporados y tratados en un fichero indicado anteriormente en las condiciones de uso del portal. @@ -53,7 +52,7 @@ es: button: "Ver preguntas frecuentes" page: title: "Preguntas Frecuentes" - description: "Utiliza esta página para resolver las Preguntas frencuentes a los usuarios del sitio." + description: "Utiliza esta página para resolver las Preguntas frecuentes a los usuarios del sitio." faq_1_title: "Pregunta 1" faq_1_description: "Este es un ejemplo para la descripción de la pregunta uno." other: @@ -62,13 +61,13 @@ es: how_to_use: text: |- Utilízalo en tu municipio libremente o ayúdanos a mejorarlo, es software libre. - + Este Portal de Gobierno Abierto usa la [aplicación CONSUL](https://github.com/consul/consul 'github consul') que es software libre, con [licencia AGPLv3](http://www.gnu.org/licenses/agpl-3.0.html 'AGPLv3 gnu' ), esto significa en palabras sencillas, que cualquiera puede libremente usar el código, copiarlo, verlo en detalle, modificarlo, y redistribuirlo al mundo con las modificaciones que quiera (manteniendo el que otros puedan a su vez hacer lo mismo). Porque creemos que la cultura es mejor y más rica cuando se libera. - + Si eres programador, puedes ver el código y ayudarnos a mejorarlo en [aplicación CONSUL](https://github.com/consul/consul 'github consul'). titles: how_to_use: Utilízalo en tu municipio - privacy: Política de Privacidad + privacy: Política de privacidad titles: accessibility: Accesibilidad conditions: Condiciones de uso diff --git a/config/locales/es/rails.yml b/config/locales/es/rails.yml index 31cc02e92..e7fa6dd42 100644 --- a/config/locales/es/rails.yml +++ b/config/locales/es/rails.yml @@ -1,58 +1,55 @@ ---- es: date: abbr_day_names: - - dom - - lun - - mar - - mié - - jue - - vie - - sáb + - dom + - lun + - mar + - mié + - jue + - vie + - sáb abbr_month_names: - - - - ene - - feb - - mar - - abr - - may - - jun - - jul - - ago - - sep - - oct - - nov - - dic + - ene + - feb + - mar + - abr + - may + - jun + - jul + - ago + - sep + - oct + - nov + - dic day_names: - - domingo - - lunes - - martes - - miércoles - - jueves - - viernes - - sábado + - domingo + - lunes + - martes + - miércoles + - jueves + - viernes + - sábado formats: default: "%d/%m/%Y" long: "%d de %B de %Y" short: "%d de %b" month_names: - - - - enero - - febrero - - marzo - - abril - - mayo - - junio - - julio - - agosto - - septiembre - - octubre - - noviembre - - diciembre + - enero + - febrero + - marzo + - abril + - mayo + - junio + - julio + - agosto + - septiembre + - octubre + - noviembre + - diciembre order: - - :day - - :month - - :year + - :day + - :month + - :year datetime: distance_in_words: about_x_hours: @@ -86,6 +83,9 @@ es: x_months: one: 1 mes other: "%{count} meses" + x_years: + one: '%{count} año' + other: "%{count} años" x_seconds: one: 1 segundo other: "%{count} segundos" @@ -113,24 +113,27 @@ es: invalid: no es válido less_than: debe ser menor que %{count} less_than_or_equal_to: debe ser menor que o igual a %{count} + model_invalid: 'Error de validación: %{errors}' not_a_number: no es un número not_an_integer: debe ser un entero odd: debe ser impar - record_invalid: 'La validación falló: %{errors}' - restrict_dependent_destroy: - one: No se puede eliminar el registro porque existe un %{record} dependiente - many: No se puede eliminar el registro porque existen %{record} dependientes + required: debe existir taken: ya está en uso - too_long: es demasiado largo (%{count} caracteres máximo) - too_short: es demasiado corto (%{count} caracteres mínimo) - wrong_length: no tiene la longitud correcta (%{count} caracteres exactos) + too_long: + one: es demasiado largo (máximo %{count} caracteres) + other: es demasiado largo (máximo %{count} caracteres) + too_short: + one: es demasiado corto (mínimo %{count} caracteres) + other: es demasiado corto (mínimo %{count} caracteres) + wrong_length: + one: longitud inválida (debería tener %{count} caracteres) + other: longitud inválida (debería tener %{count} caracteres) other_than: debe ser distinto de %{count} - invalid_date: "no es una fecha valida" template: body: 'Se encontraron problemas con los siguientes campos:' header: one: No se pudo guardar este/a %{model} porque se encontró 1 error - other: No se pudo guardar este/a %{model} porque se encontraron %{count} errores + other: "No se pudo guardar este/a %{model} porque se encontraron %{count} errores" helpers: select: prompt: Por favor seleccione @@ -163,10 +166,8 @@ es: quadrillion: mil billones thousand: mil trillion: billón - unit: '' format: - delimiter: '' - precision: 1 + precision: 3 significant: true strip_insignificant_zeros: true storage_units: @@ -174,17 +175,14 @@ es: units: byte: one: Byte - other: Bytes + other: Byte gb: GB kb: KB mb: MB tb: TB percentage: format: - delimiter: '' - precision: - format: - delimiter: '' + format: "%n%" support: array: last_word_connector: " y " @@ -193,8 +191,9 @@ es: time: am: am formats: + datetime: "%d/%m/%Y %H:%M:%S" default: "%A, %d de %B de %Y %H:%M:%S %z" long: "%d de %B de %Y %H:%M" short: "%d de %b %H:%M" - datetime: "%d/%m/%Y %H:%M:%S" + api: "%d-%m-%Y %H" pm: pm \ No newline at end of file diff --git a/config/locales/es/responders.yml b/config/locales/es/responders.yml index 74e3ea20a..cf3d11d6f 100644 --- a/config/locales/es/responders.yml +++ b/config/locales/es/responders.yml @@ -1,4 +1,3 @@ ---- es: flash: actions: @@ -8,8 +7,10 @@ es: direct_message: "Tu mensaje ha sido enviado correctamente." poll: "Votación creada correctamente." poll_booth: "Urna creada correctamente." + poll_question_answer: "Respuesta creada correctamente" + poll_question_answer_video: "Vídeo creado correctamente" proposal: "Propuesta creada correctamente." - proposal_notification: "Tu message ha sido enviado correctamente." + proposal_notification: "Tu mensaje ha sido enviado correctamente." spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}" budget_investment: "Propuesta de inversión creada correctamente." signature_sheet: "Hoja de firmas creada correctamente" @@ -19,9 +20,9 @@ es: update: notice: "%{resource_name} actualizado correctamente." debate: "Debate actualizado correctamente." - proposal: "Propuesta actualizada correctamente." poll: "Votación actualizada correctamente." poll_booth: "Urna actualizada correctamente." + proposal: "Propuesta actualizada correctamente." spending_proposal: "Propuesta de inversión actualizada correctamente." budget_investment: "Propuesta de inversión actualizada correctamente" topic: "Tema actualizado correctamente." @@ -30,3 +31,4 @@ es: budget_investment: "Propuesta de inversión eliminada." error: "No se pudo borrar" topic: "Tema eliminado." + poll_question_answer_video: "Vídeo de respuesta eliminado." diff --git a/config/locales/es/settings.yml b/config/locales/es/settings.yml index f0a7b53a2..fcf2eb1db 100644 --- a/config/locales/es/settings.yml +++ b/config/locales/es/settings.yml @@ -39,7 +39,13 @@ es: spending_proposal_features: voting_allowed: Votaciones sobre propuestas de inversión legislation: Legislación + user: + recommendations: Recomendaciones community: Comunidad en propuestas y proyectos de inversión + map: Geolocalización de propuestas y proyectos de inversión + map_latitude: Latitud + map_longitude: Longitud + map_zoom: Zoom mailer_from_name: Nombre email remitente mailer_from_address: Dirección email remitente meta_description: "Descripción del sitio (SEO)" diff --git a/config/locales/es/social_share_button.yml b/config/locales/es/social_share_button.yml index 1c49ef4f5..d624f0b0b 100644 --- a/config/locales/es/social_share_button.yml +++ b/config/locales/es/social_share_button.yml @@ -7,7 +7,7 @@ es: douban: "Douban" qq: "Qzone" tqq: "Tqq" - delicious: "Delicious" + delicious: "Delicioso" baidu: "Baidu.com" kaixin001: "Kaixin001.com" renren: "Renren.com" diff --git a/config/locales/es/valuation.yml b/config/locales/es/valuation.yml index b3a5c32ca..7c3109ab0 100644 --- a/config/locales/es/valuation.yml +++ b/config/locales/es/valuation.yml @@ -1,4 +1,3 @@ ---- es: valuation: header: @@ -25,8 +24,8 @@ es: valuation_open: Abiertas valuating: En evaluación valuation_finished: Evaluación finalizada - title: Propuestas de inversión assigned_to: "Asignadas a %{valuator}" + title: Propuestas de inversión edit: Editar informe valuators_assigned: one: Evaluador asignado @@ -62,16 +61,16 @@ es: dossier: Informe price_html: "Coste (%{currency}) (dato público)" price_first_year_html: "Coste en el primer año (%{currency}) (opcional, dato no público)" - price_explanation_html: "Informe de coste (opcional, dato público)" + price_explanation_html: Informe de coste (opcional, dato público) feasibility: Viabilidad feasible: Viable unfeasible: Inviable undefined_feasible: Sin decidir - feasible_explanation_html: "Informe de inviabilidad (en caso de que lo sea, dato público)" + feasible_explanation_html: Informe de inviabilidad (en caso de que lo sea, dato público) valuation_finished: Informe finalizado - duration_html: "Plazo de ejecución (opcional, dato no público)" - internal_comments_html: "Comentarios y observaciones (para responsables internos, dato no público)" - save: Guardar cambios + duration_html: Plazo de ejecución (opcional, dato no público) + internal_comments_html: Comentarios y observaciones (para responsables internos, dato no público) + save: Guardar Cambios notice: valuate: "Dossier actualizado" spending_proposals: @@ -111,15 +110,15 @@ es: price_html: "Coste (%{currency}) (dato público)" price_first_year_html: "Coste en el primer año (%{currency}) (opcional, privado)" currency: "€" - price_explanation_html: "Informe de coste (opcional, dato público)" + price_explanation_html: Informe de coste (opcional, dato público) feasibility: Viabilidad feasible: Viable not_feasible: Inviable undefined_feasible: Sin decidir - feasible_explanation_html: "Informe de inviabilidad (en caso de que lo sea, dato público)" + feasible_explanation_html: Informe de inviabilidad (en caso de que lo sea, dato público) valuation_finished: Informe finalizado - time_scope_html: "Plazo de ejecución (opcional, dato no público)" - internal_comments_html: "Comentarios y observaciones (para responsables internos, dato no público)" + time_scope_html: Plazo de ejecución (opcional, dato no público) + internal_comments_html: Comentarios y observaciones (para responsables internos, dato no público) save: Guardar cambios notice: valuate: "Informe actualizado" diff --git a/config/locales/es/verification.yml b/config/locales/es/verification.yml index c08900cdf..120cad17a 100644 --- a/config/locales/es/verification.yml +++ b/config/locales/es/verification.yml @@ -1,4 +1,3 @@ ---- es: verification: alert: @@ -33,7 +32,7 @@ es: office: Verificarte presencialmente en cualquier %{office} offices: Oficina de Atención al Ciudadano send_letter: Solicitar una carta por correo postal - title: "¡Felicidades!" + title: '¡Felicidades!' user_permission_info: Con tu cuenta ya puedes... update: flash: @@ -51,7 +50,7 @@ es: accept_terms_text: Acepto %{terms_url} al Padrón accept_terms_text_title: Acepto los términos de acceso al Padrón date_of_birth: Fecha de nacimiento - document_number: Número de documento + document_number: DNI/Pasaporte/Tarjeta de residencia document_number_help_title: Ayuda document_number_help_text_html: 'DNI: 12345678A
Pasaporte: AAA000001
Tarjeta de residencia: X1234567P' document_type: @@ -76,14 +75,14 @@ es: edit: confirmation_code: Introduce el código que has recibido en tu móvil resend_sms_link: Solicitar un nuevo código - resend_sms_text: "¿No has recibido un mensaje de texto con tu código de confirmación?" + resend_sms_text: '¿No has recibido un mensaje de texto con tu código de confirmación?' submit_button: Enviar title: SMS de confirmación new: phone: Introduce tu teléfono móvil para recibir el código - phone_format_html: "(Ejemplo: 612345678 ó +34612345678)" + phone_format_html: '(Ejemplo: 612345678 ó +34612345678)' phone_note: Sólo usaremos tu teléfono para enviarte un código, nunca te contactaremos. - phone_placeholder: "Ejemplo: 612345678 ó +34612345678" + phone_placeholder: 'Ejemplo: 612345678 ó +34612345678' submit_button: Enviar title: SMS de confirmación update: @@ -100,7 +99,7 @@ es: user_permission_info: Al verificar tus datos podrás... user_permission_proposal: Crear nuevas propuestas user_permission_support_proposal: Apoyar propuestas - user_permission_votes: Participar en las votaciones finales + user_permission_votes: Participar en las votaciones finales* verified_user: form: submit_button: Enviar código @@ -109,4 +108,4 @@ es: explanation: Actualmente disponemos de los siguientes datos en el Padrón, selecciona donde quieres que enviemos el código de confirmación. phone_title: Teléfonos title: Información disponible - use_another_phone: Utilizar otro teléfono + use_another_phone: Utilizar otro teléfono \ No newline at end of file diff --git a/config/locales/fr/activemodel.yml b/config/locales/fr/activemodel.yml index 8cfc22a2e..f22b0077e 100644 --- a/config/locales/fr/activemodel.yml +++ b/config/locales/fr/activemodel.yml @@ -14,10 +14,5 @@ fr: sms: phone: "Téléphone" confirmation_code: "Code de confirmation" - email: - recipient: "Courriel" officing/residence: - document_type: "Type de document" - document_number: "Numéro du document (en incluant les lettres)" year_of_birth: "Année de naissance" - diff --git a/config/locales/fr/activerecord.yml b/config/locales/fr/activerecord.yml index b588d37dc..82e9d180e 100644 --- a/config/locales/fr/activerecord.yml +++ b/config/locales/fr/activerecord.yml @@ -147,6 +147,12 @@ fr: name: Nom locale: Langue body: Contenu + poll/question/answer: + title: Réponse + description: Description + poll/question/answer/video: + title: Titre + url: Vidéo externe errors: models: user: diff --git a/config/locales/fr/admin.yml b/config/locales/fr/admin.yml index ae9a44277..b9cdfcfd3 100644 --- a/config/locales/fr/admin.yml +++ b/config/locales/fr/admin.yml @@ -377,14 +377,39 @@ fr: new: title: "Créer une question" poll_label: "Vote" - valid_answers_note: "Saisir les réponses séparées par des virgules (,)" show: proposal: Proposition originale author: Auteur title: Titre valid_answers: Réponses valides - description: Description + add_answer: Ajouter une réponse + documents: Documents (1) preview: Voir l'aperçu + answers: + title: Réponse + description: Description + videos: Vidéos + video_list: Liste des vidéos + answers: + show: + title: Titre + description: Description + images: Images + images_list: Liste des images + new: + title: Nouvelle réponse + edit: + title: Modifier réponse + videos: + index: + title: Vidéos + add_video: Ajouter une vidéo + video_title: Titre + video_url: Vidéo externe + new: + title: Nouveau vidéo + edit: + title: Modifier la vidéo recounts: index: title: "Dépouillements" diff --git a/config/locales/fr/pages.yml b/config/locales/fr/pages.yml index dcb57d400..61f86a360 100644 --- a/config/locales/fr/pages.yml +++ b/config/locales/fr/pages.yml @@ -1,4 +1,3 @@ ---- fr: pages: census_terms: Pour confirmer ce compte, vous devez être âgé(e) de 16 ans ou plus, et avoir été recensé avec les données indiquées ci-dessus, lesquelles seront vérifiées. En acceptant le processus de vérification, vous donnez également votre consentement au recoupement de cette information, ainsi que les moyens de communication qui figurent dans ce fichier. Les données fournies seront intégrées et traitées dans le fichier indiqué dans les conditions d'utilisations du portail. @@ -7,7 +6,7 @@ fr: more_info: title: "Découvrez %{org_name}" subtitle: "Découvrez tout ce qu'il est possible de faire avec ce site" - guide: "Ce guide explique chaque section de %{org_name}. Vous pouvez avoir plus d'information dans les liens 'Informations détaillées'." + guide: 'Ce guide explique chaque section de %{org_name}. Vous pouvez avoir plus d''information dans les liens ''Informations détaillées''.' menu: debates: "Débats" proposals: "Propositions" @@ -20,7 +19,7 @@ fr: feature_1_link: "vous inscrire sur %{org_name}" feature_2_html: "Les débats peuvent être notés en utilisant les boutons Je suis d'accord ou Je ne suis pas d'accord que vous trouverez dans chacun d'eux." image_alt: "Boutons pour noter les débats" - figcaption: "Les boutons 'Je suis d'accord' et 'Je ne suis pas d'accord' pour noter les débats." + figcaption: 'Les boutons ''Je suis d''accord'' et ''Je ne suis pas d''accord'' pour noter les débats.' proposals: title: "Propositions" description: "Faites une proposition sur ce que vous souhaitez que la mairie entreprenne et soutenez les propositions d'autres personnes." @@ -53,28 +52,12 @@ fr: button: "Voir les questions fréquemment posées" other: how_to_use: "Utiliser %{org_name} dans votre ville" - world: "Participation citoyenne dans le monde" - facts: "Éléments sur la participation citoyenne et la démocratie directe" how_to_use: text: |- Utilisez le librement pour votre gouvernement ou aider nous à l'améliorer, c'est un logiciel libre. - + Ce portail de Gouvernement Ouvert utilise l'[application Consul](https://github.com/consul/consul 'consul github') qui est un logiciel libre, sous [licence AGPLv3](http://www.gnu.org/licenses/agpl-3.0.html 'AGPLv3 gnu' ), ce qui, en quelques mots, signifie que tout le monde peut utiliser le code librement, le copier, le voir en détail, le modifier et le redistribuer avec ces modifications (permettant à d'autres d'en faire de même). Car nous pensons que la culture est meilleure et plus riche quand elle est libre. - + Si vous êtes un développeur, vous pouvez voir le code et nous aider à l'améliorer en allant sur l'[applicationConsul](https://github.com/consul/consul 'consul github'). - titles: - how_to_use: Utilisez-le pour votre gouvernement - privacy: Politique de confidentialité - titles: - accessibility: Accessibilité - conditions: Conditions d'utilisations - more_info: "Plus d'information à propos %{org_name}" - privacy: Politique de confidentialité verify: - code: Code que vous avez reçu par lettre - email: Courriel - info: "Pour vérifier votre compte saisissez vos données d'accès :" - info_code: 'Saisissez maintenant le code reçu par lettre :' - password: Mot de passe - submit: Confirmer mon compte - title: Confirmer mon compte + email: Email diff --git a/config/locales/fr/rails.yml b/config/locales/fr/rails.yml index 43561ec2d..a9ec187bd 100644 --- a/config/locales/fr/rails.yml +++ b/config/locales/fr/rails.yml @@ -1,160 +1,69 @@ -# Files in the config/locales directory are used for internationalization -# and are automatically loaded by Rails. If you want to use locales other -# than English, add the necessary files in this directory. -# -# To use the locales, use `I18n.t`: -# -# I18n.t 'hello' -# -# In views, this is aliased to just `t`: -# -# <%= t('hello') %> -# -# To use a different locale, set it with `I18n.locale`: -# -# I18n.locale = :es -# -# This would use the information in config/locales/es.yml. -# -# To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. - fr: date: abbr_day_names: - - dim - - lun - - mar - - mer - - jeu - - ven - - sam + - dim + - lun + - mar + - mer + - jeu + - ven + - sam abbr_month_names: - - jan - - fév - - mar - - avr - - mai - - jun - - jul - - aoû - - sep - - oct - - nov - - déc + - fév + - mar + - avr + - mai + - jun + - jul + - aoû + - sep + - oct + - nov + - déc + - Déc day_names: - - dimanche - - lundi - - mardi - - mercredi - - jeudi - - vendredi - - samedi + - dimanche + - lundi + - mardi + - mercredi + - jeudi + - vendredi + - samedi formats: default: "%d/%m/%Y" long: "%d %B %Y" short: "%d %b" month_names: - - janvier - - février - - mars - - avril - - mai - - juin - - juillet - - août - - septembre - - octobre - - novembre - - décembre - order: - - :jour - - :mois - - :année + - février + - mars + - avril + - mai + - juin + - Décembre datetime: distance_in_words: - about_x_hours: - one: environ 1 heure - other: environ %{count} heures - about_x_months: - one: environ 1 mois - other: environ %{count} mois - about_x_years: - one: environ 1 an - other: environ %{count} ans - almost_x_years: - one: presque 1 an - other: presque %{count} ans - half_a_minute: demi-minute - less_than_x_minutes: - one: moins d'1 minute - other: moins de %{count} minutes - less_than_x_seconds: - one: moins d'1 seconde - other: moins de %{count} secondes - over_x_years: - one: plus d'1 an - other: plus de %{count} ans - x_days: - one: 1 jour - other: "%{count} jours" x_minutes: one: 1 minute - other: "%{count} minutes" - x_months: - one: 1 mois other: "%{count} mois" - x_seconds: - one: 1 seconde - other: "%{count} secondes" - prompts: - day: Jour - hour: Heure - minute: Minutes - month: Mois - second: Secondes - year: Année + x_years: + one: 1 an + other: "%{count} jours" errors: format: "%{attribute} %{message}" messages: - accepted: doit être accepté - blank: ne peut pas être vide - present: doit être vide - confirmation: ne coïncide pas - empty: ne peut pas être vide - equal_to: doit être égal à %{count} - even: doit être pair - exclusion: est réservé - greater_than: doit être plus grand que %{count} - greater_than_or_equal_to: doit être plus grand que ou égal à %{count} - inclusion: n'est pas inclus dans la liste - invalid: n'est pas valide - less_than: doit être plus petit que %{count} - less_than_or_equal_to: doit être plus petit que ou égal à %{count} - not_a_number: n'est pas un nombre - not_an_integer: doit être un nombre entier - odd: doit être impair - record_invalid: 'La validation a échoué: %{errors}' - restrict_dependent_destroy: - one: Impossible de supprimer l'enregistrement car il existe un %{record} dépendant - many: Impossible de supprimer l'enregistrement car il existe des %{record} dépendants - taken: est déjà utilisé - too_long: est trop long (%{count} caractères maximum) - too_short: est trop court (%{count} caractères minimum) - wrong_length: n'a pas la bonne longueur (%{count} caractères attendus) - other_than: doit être différent de %{count} - invalid_date: "n'est pas une date valide" - template: - body: 'Des problèmes ont été trouvés avec les champs suivants :' - header: - one: Impossible d'enregistrer ce/cette %{model} car 1 erreur a été trouvée - other: Impossible d'enregistrer ce/cette %{model} car %{count} erreurs ont été trouvées + model_invalid: 'La validation omise : %{errors}' + required: doit exister + too_long: + one: est trop long (maximum est de 1 caractère) + other: est trop long (maximum est %{count} caractères) + too_short: + one: est trop long (maximum est de 1 caractère) + other: est trop long (maximum est %{count} caractères) + wrong_length: + one: est la mauvaise longueur (soit 1 caractère) + other: est la longueur incorrecte (devrait être %{count} caractères) helpers: - select: - prompt: Veuillez sélectionner submit: - create: Créer %{model} - submit: Enregistrer %{model} update: Actualiser %{model} number: currency: @@ -181,9 +90,7 @@ fr: quadrillion: quadrillion thousand: mille trillion: trillion - unit: '' format: - delimiter: '' precision: 1 significant: true strip_insignificant_zeros: true @@ -199,10 +106,7 @@ fr: tb: TO percentage: format: - delimiter: '' - precision: - format: - delimiter: '' + format: "%n %" support: array: last_word_connector: " et " @@ -211,8 +115,8 @@ fr: time: am: du matin formats: + datetime: "%d/%m/%Y %H:%M:%S" default: "%A, %d %B %Y %H:%M:%S %z" long: "%d %B %Y %H:%M" short: "%d %b %H:%M" - datetime: "%d/%m/%Y %H:%M:%S" - pm: "de l'après-midi" + pm: de l'après-midi diff --git a/config/locales/fr/responders.yml b/config/locales/fr/responders.yml index 9897e3455..1d1cfae0c 100644 --- a/config/locales/fr/responders.yml +++ b/config/locales/fr/responders.yml @@ -8,6 +8,8 @@ fr: direct_message: "Votre message a été envoyé avec succès." poll: "Vote créé avec succès." poll_booth: "Urne créée avec succès." + poll_question_answer: "Réponse créée avec succès" + poll_question_answer_video: "Vidéo créée avec succès" proposal: "Proposition créée avec succès." proposal_notification: "Votre message a correctement été envoyé." spending_proposal: "Proposition de dépense créée avec succès. Vous pouvez y accéder depuis %{activity}" @@ -27,3 +29,4 @@ fr: spending_proposal: "Proposition de dépense supprimée avec succès." budget_investment: "Budget d'investissement supprimé avec succès." error: "Suppression impossible" + poll_question_answer_video: "Réponse vidéo supprimée avec succès." diff --git a/config/locales/fr/valuation.yml b/config/locales/fr/valuation.yml index 1e1941ce2..2894f2393 100644 --- a/config/locales/fr/valuation.yml +++ b/config/locales/fr/valuation.yml @@ -1,4 +1,3 @@ ---- fr: valuation: header: @@ -14,9 +13,9 @@ fr: current: Ouvert finished: Terminé table_name: Nom - table_phase: Phase + table_phase: Phase de table_assigned_investments_valuation_open: Propositions d'investissement assignées avec une évaluation ouverte - table_actions: Actions + table_actions: Statut des votes evaluate: Évaluer budget_investments: index: @@ -35,7 +34,7 @@ fr: table_id: ID table_title: Titre table_heading_name: Nom du titre - table_actions: Actions + table_actions: Statut des votes show: back: Retour title: Propositions d'investissement @@ -62,15 +61,15 @@ fr: dossier: Rapport price_html: "Coût (%{currency})" price_first_year_html: "Coût durant la première année (%{currency}) (optionnel, données non publiques)" - price_explanation_html: "Informations sur le coût (optionnel, données publiques)" + price_explanation_html: Informations sur le coût (optionnel, données publiques) feasibility: Faisabilité feasible: Faisable unfeasible: Infaisable undefined_feasible: Indécis - feasible_explanation_html: "Informations sur la non-viabilité (le cas échéant, données publiques)" + feasible_explanation_html: Informations sur la non-viabilité (le cas échéant, données publiques) valuation_finished: Évaluation terminée - duration_html: "Délai d'exécution (optionnel, données non publiques)" - internal_comments_html: "Commentaires et observations (pour les responsables internes, données non publiques)" + duration_html: Délai d'exécution (optionnel, données non publiques) + internal_comments_html: Commentaires et observations (pour les responsables internes, données non publiques) save: Enregistrer les changements notice: valuate: "Rapport mis-à-jour" @@ -111,17 +110,15 @@ fr: price_html: "Coût (%{currency}) (données publiques)" price_first_year_html: "Coût durant la première année (%{currency}) (optionnel, données non publiques)" currency: "€" - price_explanation_html: "Informations sur le coût (optionnel, données publiques)" + price_explanation_html: Informations sur le coût (optionnel, données publiques) feasibility: Faisabilité feasible: Faisable not_feasible: Infaisable undefined_feasible: Indécis - feasible_explanation_html: "Informations sur la non-viabilité (le cas échéant, données publiques)" + feasible_explanation_html: Informations sur la non-viabilité (le cas échéant, données publiques) valuation_finished: Évaluation terminée - time_scope_html: "Délai d'exécution (optionnel, données non publiques)" - internal_comments_html: "Commentaires et observations (pour les responsables internes, données non publiques)" + time_scope_html: Délai d'exécution (optionnel, données non publiques) + internal_comments_html: Commentaires et observations (pour les responsables internes, données non publiques) save: Enregistrer les changements notice: valuate: "Informations actualisées" - - diff --git a/config/locales/gl/rails.yml b/config/locales/gl/rails.yml new file mode 100644 index 000000000..9dda51249 --- /dev/null +++ b/config/locales/gl/rails.yml @@ -0,0 +1,13 @@ +gl: + number: + currency: + format: + significant: false + strip_insignificant_zeros: false + format: + significant: false + strip_insignificant_zeros: false + human: + format: + significant: true + strip_insignificant_zeros: true diff --git a/config/locales/he/rails.yml b/config/locales/he/rails.yml new file mode 100644 index 000000000..853576daa --- /dev/null +++ b/config/locales/he/rails.yml @@ -0,0 +1,13 @@ +he: + number: + currency: + format: + significant: false + strip_insignificant_zeros: false + format: + significant: false + strip_insignificant_zeros: false + human: + format: + significant: true + strip_insignificant_zeros: true diff --git a/config/locales/it/activemodel.yml b/config/locales/it/activemodel.yml new file mode 100644 index 000000000..9a8b71a8b --- /dev/null +++ b/config/locales/it/activemodel.yml @@ -0,0 +1,22 @@ +it: + activemodel: + models: + verification: + residence: "Residenza" + sms: "SMS" + attributes: + verification: + residence: + document_type: "Tipo Documento di identità" + document_number: "N. Documento" + date_of_birth: "Data di nascita" + postal_code: "CAP" + sms: + phone: "Telefono" + confirmation_code: "Codice di conferma" + email: + recipient: "E-mail" + officing/residence: + document_type: "Tipo Documento di identità" + document_number: "Numero del documento (lettere incluse)" + year_of_birth: "Anno di nascita" diff --git a/config/locales/it/community.yml b/config/locales/it/community.yml new file mode 100644 index 000000000..c976b29ee --- /dev/null +++ b/config/locales/it/community.yml @@ -0,0 +1,4 @@ +it: + community: + sidebar: + title: Comunità diff --git a/config/locales/it/documents.yml b/config/locales/it/documents.yml new file mode 100644 index 000000000..565fb4d90 --- /dev/null +++ b/config/locales/it/documents.yml @@ -0,0 +1,3 @@ +it: + documents: + tab: Documenti diff --git a/config/locales/it/general.yml b/config/locales/it/general.yml new file mode 100644 index 000000000..c0309e872 --- /dev/null +++ b/config/locales/it/general.yml @@ -0,0 +1,756 @@ +it: + account: + show: + email_on_comment_label: "" + email_on_comment_reply_label: "" + erase_account_link: "" + finish_verification: "" + notifications: "" + organization_name_label: "" + organization_responsible_name_placeholder: "" + personal: "" + phone_number_label: "" + public_activity_label: "" + public_interests_label: "" + public_interests_my_title_list: "" + public_interests_user_title_list: "" + public_interests_my_empty_list: "" + public_interests_user_empty_list: "" + save_changes_submit: "" + subscription_to_website_newsletter_label: "" + email_on_direct_message_label: "" + email_digest_label: "" + official_position_badge_label: "" + title: "" + user_permission_debates: "" + user_permission_info: "" + user_permission_proposal: "" + user_permission_support_proposal: "" + user_permission_title: "" + user_permission_verify: "" + user_permission_verify_info: "" + user_permission_votes: "" + username_label: "" + verified_account: "" + verify_my_account: "" + application: + close: "" + menu: "" + comments: + comments_closed: "" + verified_only: "" + verify_account: "" + comment: + admin: "" + author: "" + deleted: "" + moderator: "" + responses: + one: "" + other: "" + user_deleted: "" + votes: + one: "" + other: "" + form: + comment_as_admin: "" + comment_as_moderator: "" + leave_comment: "" + orders: + most_voted: "" + newest: "" + oldest: "" + most_commented: "" + select_order: "" + show: + return_to_commentable: '' + comments_helper: + comment_button: "" + comment_link: "" + comments_title: "" + reply_button: "" + reply_link: "" + debates: + create: + form: + submit_button: "" + debate: + comments: + one: "" + other: "" + votes: + one: "" + other: "" + edit: + editing: "" + form: + submit_button: "" + show_link: "" + form: + debate_text: "" + debate_title: "" + tags_instructions: "" + tags_label: "" + tags_placeholder: "" + index: + featured_debates: "" + filter_topic: + one: "" + other: "" + orders: + confidence_score: "" + created_at: "" + hot_score: "" + most_commented: "" + relevance: "" + search_form: + button: "" + placeholder: "" + title: "" + search_results_html: + one: "" + other: "" + select_order: "" + start_debate: "" + title: "" + section_header: + icon_alt: "" + title: "" + help: "" + section_footer: + title: "" + description: "" + help_text_1: "" + help_text_2: '' + help_text_3: "" + proposals_link: "" + budget_link: "" + new: + form: + submit_button: "" + info: "" + info_link: "" + more_info: "" + recommendation_four: "" + recommendation_one: "" + recommendation_three: "" + recommendation_two: "" + recommendations_title: "" + start_new: "" + show: + author_deleted: "" + comments: + one: "" + other: "" + comments_title: "" + edit_debate_link: "" + flag: "" + login_to_comment: "" + share: "" + update: + form: + submit_button: "" + errors: + messages: + user_not_found: "" + invalid_date_range: "" + form: + accept_terms: "" + accept_terms_title: "" + conditions: "" + debate: "" + direct_message: "" + error: "" + errors: "" + not_saved: '' + policy: "" + proposal: "" + proposal_notification: "" + spending_proposal: "" + budget/investment: "" + poll/shift: "" + user: "" + verification/sms: "" + signature_sheet: "" + document: "" + topic: "" + geozones: + none: "" + all: "" + layouts: + application: + chrome: "" + firefox: "" + ie: "" + ie_title: "" + footer: + accessibility: "" + conditions: "" + consul: "" + consul_url: "" + contact_us: "" + copyright: "" + description: "" + faq: "" + open_data_text: "" + open_data_title: "" + open_source: "" + open_source_url: "" + participation_text: "" + participation_title: "" + privacy: "" + transparency_text: "" + transparency_title: "" + transparency_url: "" + header: + administration_menu: "" + administration: "" + available_locales: "" + collaborative_legislation: "" + debates: "" + external_link_blog: "" + external_link_opendata: "" + external_link_opendata_url: "" + external_link_transparency: "" + external_link_transparency_url: "" + locale: '' + logo: "" + management: "" + moderation: "" + valuation: "" + officing: "" + more_info: "" + my_account_link: "" + my_activity_link: "" + notifications: "" + new_notifications: + one: "" + other: "" + no_notifications: "" + open: "" + open_city_slogan_html: "" + open_city_title: "" + open_gov: "" + proposals: "" + poll_questions: "" + budgets: "" + spending_proposals: "" + admin: + watch_form_message: '' + legacy_legislation: + help: + alt: "" + text: "" + text_sign_in: "" + text_sign_up: "" + title: "" + locale: "" + notifications: + index: + comments_on: + one: "" + other: "" + empty_notifications: "" + mark_all_as_read: "" + proposal_notification: + one: "" + other: "" + replies_to: + one: "" + other: "" + title: "" + map: + title: "" + proposal_for_district: "" + select_district: "" + start_proposal: "" + omniauth: + facebook: + sign_in: "" + sign_up: "" + name: "" + finish_signup: + title: "" + username_warning: "" + google_oauth2: + sign_in: "" + sign_up: "" + name: "" + twitter: + sign_in: "" + sign_up: "" + name: "" + info_sign_in: "" + info_sign_up: "" + or_fill: "" + proposals: + create: + form: + submit_button: "" + edit: + editing: "" + form: + submit_button: "" + show_link: "" + retire_form: + title: "" + warning: "" + retired_reason_label: "" + retired_reason_blank: "" + retired_explanation_label: "" + retired_explanation_placeholder: "" + submit_button: "" + retire_options: + duplicated: "" + started: "" + unfeasible: "" + done: "" + other: "" + form: + geozone: "" + proposal_external_url: "" + proposal_question: "" + proposal_question_example_html: "" + proposal_responsible_name: "" + proposal_responsible_name_note: "" + proposal_summary: "" + proposal_summary_note: "" + proposal_text: "" + proposal_title: "" + proposal_video_url: "" + proposal_video_url_note: "" + tag_category_label: "" + tags_instructions: "" + tags_label: "" + tags_placeholder: "" + index: + featured_proposals: "" + filter_topic: + one: "" + other: "" + orders: + confidence_score: "" + created_at: "" + hot_score: "" + most_commented: "" + relevance: "" + archival_date: "" + retired_proposals: "" + retired_proposals_link: "" + retired_links: + all: "" + duplicated: "" + started: "" + unfeasible: "" + done: "" + other: "" + search_form: + button: "" + placeholder: "" + title: "" + search_results_html: + one: "" + other: "" + select_order: "" + select_order_long: '' + start_proposal: "" + title: "" + top: "" + top_link_proposals: "" + section_header: + icon_alt: "" + title: "" + help: "" + section_footer: + title: "" + description: "" + help_text_1: "" + help_text_2: "" + help_text_3: "" + new: + form: + submit_button: "" + more_info: "" + recommendation_one: "" + recommendation_three: "" + recommendation_two: "" + recommendations_title: "" + start_new: "" + notice: + retired: "" + proposal: + created: "" + share: + guide: "" + edit: "" + view_proposal: "" + improve_info: "" + improve_info_link: "" + already_supported: "" + comments: + one: "" + other: "" + reason_for_supports_necessary: "" + support: "" + support_title: "" + supports: + one: "" + other: "" + supports_necessary: "" + total_percent: "" + archived: "" + successful: "" + voting: "" + show: + author_deleted: "" + code: '' + comments: + one: "" + other: "" + comments_tab: "" + edit_proposal_link: "" + flag: "" + login_to_comment: "" + notifications_tab: "" + retired_warning: "" + retired_warning_link_to_explanation: "" + retired: "" + share: "" + send_notification: "" + no_notifications: "" + embed_video_title: "" + title_external_url: "" + title_video_url: "" + author: "" + update: + form: + submit_button: "" + polls: + all: "" + no_dates: "" + dates: "" + final_date: "" + index: + filters: + current: "" + incoming: "" + expired: "" + title: "" + participate_button: "" + participate_button_incoming: "" + participate_button_expired: "" + no_geozone_restricted: "" + geozone_restricted: "" + geozone_info: "" + can_answer: "" + cant_answer: "" + cant_answer_not_logged_in: "" + cant_answer_verify: "" + already_answer: "" + section_header: + icon_alt: "" + title: "" + help: "" + section_footer: + title: "" + description: "" + help_text_1: "" + help_text_2: "" + show: + dates_title: "" + cant_answer_not_logged_in: "" + signin: "" + signup: "" + cant_answer_verify_html: "" + verify_link: "" + cant_answer_incoming: "" + cant_answer_expired: "" + poll_questions: + create_question: "" + default_valid_answers: "" + show: + answer_this_question: "" + original_proposal: "" + author: "" + dates_title: "" + more_info: "" + not_logged_in: "" + signin: "" + signup: "" + cant_answer_verify_html: "" + verify_link: "" + cant_answer_incoming: "" + cant_answer_expired: "" + cant_answer_wrong_geozone: "" + vote_answer: "" + voted: "" + poll: "" + proposal_notifications: + new: + title: "" + title_label: "" + body_label: "" + submit_button: "" + info_about_receivers_html: "" + proposal_page: "" + show: + back: "" + shared: + edit: '' + save: '' + delete: "" + comments: + title: '' + login_to_comment: '' + "yes": "" + "no": "" + search_results: "" + advanced_search: + author_type: '' + author_type_blank: '' + date: '' + date_placeholder: '' + date_range_blank: '' + date_1: '' + date_2: '' + date_3: '' + date_4: '' + date_5: '' + from: '' + general: '' + general_placeholder: '' + search: '' + title: '' + to: '' + author_info: + author_deleted: "" + back: "" + check: "" + check_all: "" + check_none: "" + collective: "" + flag: "" + follow: "" + follow_entity: "" + followable: + budget_investment: + create: + notice_html: "" + destroy: + notice_html: "" + proposal: + create: + notice_html: "" + destroy: + notice_html: "" + hide: "" + print: + print_button: "" + search: "" + show: "" + suggest: + debate: + found: + one: "" + other: "" + message: "" + see_all: "" + budget_investment: + found: + one: "" + other: "" + message: "" + see_all: "" + proposal: + found: + one: "" + other: "" + message: "" + see_all: "" + tags_cloud: + tags: "" + districts: "" + districts_list: "" + categories: "" + target_blank_html: "" + you_are_in: "" + unflag: "" + unfollow: "" + unfollow_entity: "" + outline: + budget: "" + searcher: "" + go_to_page: "" + social: + blog: "" + facebook: "" + twitter: "" + youtube: "" + whatsapp: "" + telegram: "" + instagram: "" + spending_proposals: + form: + association_name_label: '' + association_name: '' + description: "" + external_url: "" + geozone: "" + submit_buttons: + create: "" + new: "" + title: "" + index: + title: "" + unfeasible: "" + by_geozone: "" + search_form: + button: "" + placeholder: "" + title: "" + search_results: + one: "" + other: "" + sidebar: + geozones: "" + feasibility: "" + unfeasible: "" + start_spending_proposal: "" + new: + more_info: "" + recommendation_one: "" + recommendation_three: "" + recommendation_two: "" + recommendations_title: "" + start_new: "" + show: + author_deleted: "" + code: '' + share: "" + wrong_price_format: "" + spending_proposal: + spending_proposal: "" + already_supported: "" + support: "" + support_title: "" + supports: + one: "" + other: "" + stats: + index: + visits: "" + debates: "" + proposals: "" + comments: "" + proposal_votes: "" + debate_votes: "" + comment_votes: "" + votes: "" + verified_users: "" + unverified_users: "" + unauthorized: + default: "" + manage: + all: "" + users: + direct_messages: + new: + body_label: "" + direct_messages_bloqued: "" + submit_button: "" + title: "" + title_label: "" + verified_only: "" + verify_account: "" + authenticate: "" + signin: "" + signup: "" + show: + receiver: "" + show: + deleted: "" + deleted_debate: "" + deleted_proposal: "" + deleted_budget_investment: "" + filters: + comments: + one: "" + other: "" + debates: + one: "" + other: "" + proposals: + one: "" + other: "" + budget_investments: + one: "" + other: "" + follows: + one: "" + other: "" + no_activity: "" + no_private_messages: "" + private_activity: "" + send_private_message: "" + proposals: + send_notification: "" + retire: "" + retired: "" + see: "" + votes: + agree: "" + anonymous: "" + comment_unauthenticated: "" + disagree: "" + organizations: "" + signin: "" + signup: "" + supports: "" + unauthenticated: "" + verified_only: "" + verify_account: "" + spending_proposals: + not_logged_in: "" + not_verified: "" + organization: "" + unfeasible: "" + not_voting_allowed: "" + budget_investments: + not_logged_in: "" + not_verified: "" + organization: "" + unfeasible: "" + not_voting_allowed: "" + different_heading_assigned: "" + welcome: + debates: + description: "" + title: "" + decide: + description: "" + title: "" + do: + description: "" + title: "" + proposal: + description: "" + title: "" + verification: + i_dont_have_an_account: "" + i_have_an_account: "" + question: "" + title: "" + welcome: + go_to_index: "" + title: "" + user_permission_debates: "" + user_permission_info: "" + user_permission_proposal: "" + user_permission_support_proposal: "" + user_permission_verify: "" + user_permission_verify_info: "" + user_permission_verify_my_account: "" + user_permission_votes: "" + invisible_captcha: + sentence_for_humans: "" + timestamp_error_message: "" diff --git a/config/locales/it/images.yml b/config/locales/it/images.yml new file mode 100644 index 000000000..7698aa371 --- /dev/null +++ b/config/locales/it/images.yml @@ -0,0 +1,3 @@ +it: + images: + remove_image: Rimuovere immagine diff --git a/config/locales/it/rails.yml b/config/locales/it/rails.yml new file mode 100644 index 000000000..6500a297e --- /dev/null +++ b/config/locales/it/rails.yml @@ -0,0 +1,13 @@ +it: + number: + currency: + format: + significant: false + strip_insignificant_zeros: false + format: + significant: false + strip_insignificant_zeros: false + human: + format: + significant: true + strip_insignificant_zeros: true diff --git a/config/locales/nl/rails.yml b/config/locales/nl/rails.yml index d5613a3d7..574380f47 100644 --- a/config/locales/nl/rails.yml +++ b/config/locales/nl/rails.yml @@ -1,81 +1,55 @@ -# Files in the config/locales directory are used for internationalization -# and are automatically loaded by Rails. If you want to use locales other -# than English, add the necessary files in this directory. -# -# To use the locales, use `I18n.t`: -# -# I18n.t 'hello' -# -# In views, this is aliased to just `t`: -# -# <%= t('hello') %> -# -# To use a different locale, set it with `I18n.locale`: -# -# I18n.locale = :es -# -# This would use the information in config/locales/es.yml. -# -# To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. - nl: - time: - formats: - datetime: "%Y-%m-%d %H:%M:%S" date: abbr_day_names: - - zo - - ma - - di - - wo - - do - - vr - - za + - zo + - ma + - di + - wo + - do + - vr + - za abbr_month_names: - - - - jan - - feb - - mrt - - apr - - mei - - jun - - jul - - aug - - sep - - okt - - nov - - dec + - jan + - feb + - mrt + - apr + - mei + - jun + - jul + - aug + - sep + - okt + - nov + - dec day_names: - - zondag - - maandag - - dinsdag - - woensdag - - donderdag - - vrijdag - - zaterdag + - zondag + - maandag + - dinsdag + - woensdag + - donderdag + - vrijdag + - zaterdag formats: default: "%d-%m-%Y" long: "%e %B %Y" short: "%e %b" month_names: - - - - januari - - februari - - maart - - april - - mei - - juni - - juli - - augustus - - september - - oktober - - november - - december + - januari + - februari + - maart + - april + - mei + - juni + - juli + - augustus + - september + - oktober + - november + - december order: - - :day - - :month - - :year + - :day + - ': month' + - :year datetime: distance_in_words: about_x_hours: @@ -109,6 +83,9 @@ nl: x_months: one: 1 maand other: "%{count} maanden" + x_years: + one: '%{count} jaar' + other: "%{count} jaar" x_seconds: one: 1 seconde other: "%{count} seconden" @@ -136,14 +113,10 @@ nl: invalid: is ongeldig less_than: moet minder zijn dan %{count} less_than_or_equal_to: moet minder dan of gelijk zijn aan %{count} - model_invalid: "Validatie mislukt: %{errors}" + model_invalid: 'Validatie mislukt: %{errors}' not_a_number: is geen getal not_an_integer: moet een geheel getal zijn odd: moet oneven zijn - record_invalid: 'Validatie mislukt: %{errors}' - restrict_dependent_destroy: - one: Kan item niet verwijderen omdat %{record} afhankelijk is - many: Kan item niet verwijderen omdat afhankelijke %{record} bestaan required: moet bestaan taken: is al in gebruik too_long: @@ -159,15 +132,15 @@ nl: template: body: 'Er zijn problemen met de volgende velden:' header: - one: "%{model} niet opgeslagen: 1 fout gevonden" + one: '%{model} niet opgeslagen: 1 fout gevonden' other: "%{model} niet opgeslagen: %{count} fouten gevonden" helpers: select: prompt: Maak een keuze submit: - create: "%{model} toevoegen" - submit: "%{model} opslaan" - update: "%{model} bijwerken" + create: '%{model} toevoegen' + submit: '%{model} opslaan' + update: '%{model} bijwerken' number: currency: format: @@ -193,9 +166,7 @@ nl: quadrillion: biljard thousand: duizend trillion: biljoen - unit: '' format: - delimiter: '' precision: 3 significant: true strip_insignificant_zeros: true @@ -211,20 +182,17 @@ nl: tb: TB percentage: format: - delimiter: '' format: "%n%" - precision: - format: - delimiter: '' support: array: last_word_connector: " en " two_words_connector: " en " words_connector: ", " time: - am: "'s ochtends" + am: '''s ochtends' formats: + datetime: "%Y-%m-%d %H:%M:%S" default: "%a %d %b %Y %H:%M:%S %Z" long: "%d %B %Y %H:%M" short: "%d %b %H:%M" - pm: "'s middags" + pm: '''s middags' diff --git a/config/locales/nl/valuation.yml b/config/locales/nl/valuation.yml deleted file mode 100644 index 5ff8a79c8..000000000 --- a/config/locales/nl/valuation.yml +++ /dev/null @@ -1,127 +0,0 @@ ---- -nl: - valuation: - header: - title: Valuation - menu: - title: Valuation - budgets: Participatory budgets - spending_proposals: Spending proposals - budgets: - index: - title: Participatory budgets - filters: - current: Open - finished: Finished - table_name: Name - table_phase: Phase - table_assigned_investments_valuation_open: Investment projects assigned with valuation open - table_actions: Actions - evaluate: Evaluate - budget_investments: - index: - headings_filter_all: All headings - filters: - valuation_open: Open - valuating: Under valuation - valuation_finished: Valuation finished - assigned_to: "Assigned to %{valuator}" - title: Investment projects - edit: Edit dossier - valuators_assigned: - one: Assigned valuator - other: "%{count} valuators assigned" - no_valuators_assigned: No valuators assigned - table_id: ID - table_title: Title - table_heading_name: Heading name - table_actions: Actions - show: - back: Back - title: Investment project - info: Author info - by: Sent by - sent: Sent at - heading: Heading - dossier: Dossier - edit_dossier: Edit dossier - price: Price - price_first_year: Cost during the first year - currency: "€" - feasibility: Feasibility - feasible: Feasible - unfeasible: Unfeasible - undefined: Undefined - valuation_finished: Valuation finished - duration: Time scope - internal_comments: Internal comments - responsibles: Responsibles - assigned_admin: Assigned admin - assigned_valuators: Assigned valuators - edit: - dossier: Dossier - price_html: "Price (%{currency})" - price_first_year_html: "Cost during the first year (%{currency}) (optional, data not public)" - price_explanation_html: Price explanation - feasibility: Feasibility - feasible: Feasible - unfeasible: Not feasible - undefined_feasible: Pending - feasible_explanation_html: Feasibility explanation - valuation_finished: Valuation finished - duration_html: Time scope - internal_comments_html: Internal comments - save: Save changes - notice: - valuate: "Dossier updated" - spending_proposals: - index: - geozone_filter_all: All zones - filters: - valuation_open: Open - valuating: Under valuation - valuation_finished: Valuation finished - title: Investment projects for participatory budgeting - edit: Edit - show: - back: Back - heading: Investment project - info: Author info - association_name: Asociación - by: Sent by - sent: Sent at - geozone: Scope - dossier: Dossier - edit_dossier: Edit dossier - price: Price - price_first_year: Cost during the first year - currency: "€" - feasibility: Feasibility - feasible: Feasible - not_feasible: Not feasible - undefined: Undefined - valuation_finished: Valuation finished - time_scope: Time scope - internal_comments: Internal comments - responsibles: Responsibles - assigned_admin: Assigned admin - assigned_valuators: Assigned valuators - edit: - dossier: Dossier - price_html: "Price (%{currency})" - price_first_year_html: "Cost during the first year (%{currency})" - currency: "€" - price_explanation_html: Price explanation - feasibility: Feasibility - feasible: Feasible - not_feasible: Not feasible - undefined_feasible: Pending - feasible_explanation_html: Feasibility explanation - valuation_finished: Valuation finished - time_scope_html: Time scope - internal_comments_html: Internal comments - save: Save changes - notice: - valuate: "Dossier updated" - - diff --git a/config/locales/pt-BR/general.yml b/config/locales/pt-BR/general.yml index 816c14fa2..bfe4124f7 100644 --- a/config/locales/pt-BR/general.yml +++ b/config/locales/pt-BR/general.yml @@ -362,7 +362,6 @@ pt-BR: - Sex - Sab abbr_month_names: - - - Jan - Fev - Mar diff --git a/config/locales/pt-BR/rails.yml b/config/locales/pt-BR/rails.yml new file mode 100644 index 000000000..2a5eab69c --- /dev/null +++ b/config/locales/pt-BR/rails.yml @@ -0,0 +1,13 @@ +pt-BR: + number: + currency: + format: + significant: false + strip_insignificant_zeros: false + format: + significant: false + strip_insignificant_zeros: false + human: + format: + significant: true + strip_insignificant_zeros: true diff --git a/config/locales/sv-SE/rails.yml b/config/locales/sv-SE/rails.yml new file mode 100644 index 000000000..9d92c753c --- /dev/null +++ b/config/locales/sv-SE/rails.yml @@ -0,0 +1,13 @@ +sv: + number: + currency: + format: + significant: false + strip_insignificant_zeros: false + format: + significant: false + strip_insignificant_zeros: false + human: + format: + significant: true + strip_insignificant_zeros: true diff --git a/config/routes.rb b/config/routes.rb index a02384ced..9ce97f45b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,17 +6,17 @@ Rails.application.routes.draw do end devise_for :users, controllers: { - registrations: 'users/registrations', - sessions: 'users/sessions', - confirmations: 'users/confirmations', - omniauth_callbacks: 'users/omniauth_callbacks' - } + registrations: 'users/registrations', + sessions: 'users/sessions', + confirmations: 'users/confirmations', + omniauth_callbacks: 'users/omniauth_callbacks' + } devise_for :organizations, class_name: 'User', - controllers: { - registrations: 'organizations/registrations', - sessions: 'devise/sessions', - }, - skip: [:omniauth_callbacks] + controllers: { + registrations: 'organizations/registrations', + sessions: 'devise/sessions' + }, + skip: [:omniauth_callbacks] devise_scope :organization do get 'organizations/sign_up/success', to: 'organizations/registrations#success' @@ -78,7 +78,9 @@ Rails.application.routes.draw do resources :budgets, only: [:show, :index] do resources :groups, controller: "budgets/groups", only: [:show] resources :investments, controller: "budgets/investments", only: [:index, :new, :create, :show, :destroy] do - member { post :vote } + member do + post :vote + end collection { get :suggest } end resource :ballot, only: :show, controller: "budgets/ballots" do @@ -95,13 +97,12 @@ Rails.application.routes.draw do resources :follows, only: [:create, :destroy] - resources :documents, only: [:new, :create, :destroy] do - collection do - get :new_nested - delete :destroy_upload - post :upload - end - end + resources :documents, only: [:destroy] + + resources :images, only: [:destroy] + + resources :direct_uploads, only: [:create] + delete "direct_uploads/destroy", to: "direct_uploads#destroy", as: :direct_upload_destroy resources :stats, only: [:index] @@ -112,7 +113,11 @@ Rails.application.routes.draw do end resources :polls, only: [:show, :index] do - resources :questions, only: [:show], controller: 'polls/questions', shallow: true do + member do + get :stats + get :results + end + resources :questions, controller: 'polls/questions', shallow: true do post :answer, on: :member end end @@ -124,10 +129,22 @@ Rails.application.routes.draw do get :draft_publication get :allegations get :result_publication + get :proposals end resources :questions, only: [:show] do resources :answers, only: [:create] end + resources :proposals do + member do + post :vote + put :flag + put :unflag + end + collection do + get :map + get :suggest + end + end resources :draft_versions, only: [:show] do get :go_to_version, on: :collection get :changes @@ -168,6 +185,11 @@ Rails.application.routes.draw do resource :letter, controller: "letter", only: [:new, :create, :show, :edit, :update] end + resources :tags do + collection do + get :suggest + end + end namespace :admin do root to: "dashboard#index" @@ -244,11 +266,13 @@ Rails.application.routes.draw do end resources :settings, only: [:index, :update] + put :update_map, to: "settings#update_map" + resources :moderators, only: [:index, :create, :destroy] do get :search, on: :collection end - resources :valuators, only: [:index, :create] do + resources :valuators, only: [:index, :create, :destroy] do get :search, on: :collection get :summary, on: :collection end @@ -265,12 +289,12 @@ Rails.application.routes.draw do scope module: :poll do resources :polls do - get :search_questions, on: :member + get :booth_assignments, on: :collection patch :add_question, on: :member - patch :remove_question, on: :member resources :booth_assignments, only: [:index, :show, :create, :destroy] do get :search_booths, on: :collection + get :manage, on: :collection end resources :officer_assignments, only: [:index, :create, :destroy] do @@ -294,7 +318,14 @@ Rails.application.routes.draw do end end - resources :questions + resources :questions, shallow: true do + resources :answers, except: [:index, :destroy], controller: 'questions/answers', shallow: true do + resources :images, controller: 'questions/answers/images' + resources :videos, controller: 'questions/answers/videos' + get :documents, to: 'questions/answers#documents' + end + post '/answers/order_answers', to: 'questions/answers#order_answers' + end end resources :verifications, controller: :verifications, only: :index do @@ -313,6 +344,7 @@ Rails.application.routes.draw do namespace :legislation do resources :processes do resources :questions + resources :proposals resources :draft_versions end end @@ -431,9 +463,7 @@ Rails.application.routes.draw do get '/graphql', to: 'graphql#query' post '/graphql', to: 'graphql#query' - if Rails.env.development? - mount LetterOpenerWeb::Engine, at: "/letter_opener" - end + mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development? mount GraphiQL::Rails::Engine, at: '/graphiql', graphql_path: '/graphql' diff --git a/config/secrets.yml.example b/config/secrets.yml.example index f67ea65c0..3939d7b80 100644 --- a/config/secrets.yml.example +++ b/config/secrets.yml.example @@ -1,41 +1,74 @@ default: &default - secret_key_base: "56792feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4" + secret_key_base: 56792feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4 -development: - <<: *default - -test: - <<: *default - -staging: - server_name: "" - <<: *default - -production: &production - secret_key_base: "817232feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4" +maps: &maps + map_tiles_provider: "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" + map_tiles_provider_attribution: "© OpenStreetMap contributors" +apis: &apis census_api_end_point: "" census_api_institution_code: "" census_api_portal_name: "" census_api_user_code: "" - sms_end_point: "" sms_username: "" sms_password: "" +http_basic_auth: &http_basic_auth + http_basic_auth: true + + +development: + http_basic_username: "dev" + http_basic_password: "pass" + <<: *default + +test: + <<: *default + <<: *maps + +staging: + secret_key_base: "" + server_name: "" + rollbar_server_token: "" http_basic_username: "" http_basic_password: "" + managers_url: "" + managers_application_key: "" + <<: *default + <<: *maps + <<: *apis +preproduction: + secret_key_base: "" + server_name: "" + rollbar_server_token: "" + http_basic_username: "" + http_basic_password: "" + managers_url: "" + managers_application_key: "" twitter_key: "" twitter_secret: "" facebook_key: "" facebook_secret: "" google_oauth2_key: "" google_oauth2_secret: "" + <<: *maps + <<: *apis +production: + secret_key_base: "" + server_name: "" rollbar_server_token: "" - server_name: "" - -preproduction: - server_name: "" - <<: *production + http_basic_username: "" + http_basic_password: "" + managers_url: "" + managers_application_key: "" + twitter_key: "" + twitter_secret: "" + facebook_key: "" + facebook_secret: "" + google_oauth2_key: "" + google_oauth2_secret: "" + <<: *maps + <<: *apis diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index 1223d94a4..60493e0a5 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -1,353 +1,370 @@ require 'database_cleaner' - DatabaseCleaner.clean_with :truncation +@logger = Logger.new(STDOUT) +@logger.formatter = proc { |_severity, _datetime, _progname, msg| msg } -print "Creating Settings" -Setting.create(key: 'official_level_1_name', value: 'Empleados públicos') -Setting.create(key: 'official_level_2_name', value: 'Organización Municipal') -Setting.create(key: 'official_level_3_name', value: 'Directores generales') -Setting.create(key: 'official_level_4_name', value: 'Concejales') -Setting.create(key: 'official_level_5_name', value: 'Alcaldesa') -Setting.create(key: 'max_ratio_anon_votes_on_debates', value: '50') -Setting.create(key: 'max_votes_for_debate_edit', value: '1000') -Setting.create(key: 'max_votes_for_proposal_edit', value: '1000') -Setting.create(key: 'proposal_code_prefix', value: 'MAD') -Setting.create(key: 'votes_for_proposal_success', value: '100') -Setting.create(key: 'months_to_archive_proposals', value: '12') -Setting.create(key: 'comments_body_max_length', value: '1000') - -Setting.create(key: 'twitter_handle', value: '@consul_dev') -Setting.create(key: 'twitter_hashtag', value: '#consul_dev') -Setting.create(key: 'facebook_handle', value: 'CONSUL') -Setting.create(key: 'youtube_handle', value: 'CONSUL') -Setting.create(key: 'telegram_handle', value: 'CONSUL') -Setting.create(key: 'instagram_handle', value: 'CONSUL') -Setting.create(key: 'blog_url', value: '/blog') -Setting.create(key: 'url', value: 'http://localhost:3000') -Setting.create(key: 'org_name', value: 'CONSUL') -Setting.create(key: 'place_name', value: 'City') -Setting.create(key: 'feature.debates', value: "true") -Setting.create(key: 'feature.polls', value: "true") -Setting.create(key: 'feature.spending_proposals', value: nil) -Setting.create(key: 'feature.spending_proposal_features.voting_allowed', value: nil) -Setting.create(key: 'feature.budgets', value: "true") -Setting.create(key: 'feature.twitter_login', value: "true") -Setting.create(key: 'feature.facebook_login', value: "true") -Setting.create(key: 'feature.google_login', value: "true") -Setting.create(key: 'feature.signature_sheets', value: "true") -Setting.create(key: 'feature.legislation', value: "true") -Setting.create(key: 'feature.community', value: "true") -Setting.create(key: 'per_page_code_head', value: "") -Setting.create(key: 'per_page_code_body', value: "") -Setting.create(key: 'comments_body_max_length', value: '1000') -Setting.create(key: 'mailer_from_name', value: 'CONSUL') -Setting.create(key: 'mailer_from_address', value: 'noreply@consul.dev') -Setting.create(key: 'meta_description', value: 'Citizen Participation and Open Government Application') -Setting.create(key: 'meta_keywords', value: 'citizen participation, open government') -Setting.create(key: 'verification_offices_url', value: 'http://oficinas-atencion-ciudadano.url/') -Setting.create(key: 'min_age_to_participate', value: '16') -Setting.create(key: 'proposal_improvement_path', value: nil) - -puts " ✅" -print "Creating Geozones" - -Geozone.create(name: "city") -Geozone.create(name: "Existent District", census_code: "01") -('A'..'Z').each { |i| Geozone.create(name: "District #{i}", external_code: i.ord, census_code: i.ord) } - -puts " ✅" -print "Creating Users" - -def create_user(email, username = Faker::Name.name) - pwd = '12345678' - User.create!( - username: username, - email: email, - password: pwd, - password_confirmation: pwd, - confirmed_at: Time.current, - terms_of_service: "1", - gender: ['Male', 'Female'].sample, - date_of_birth: rand((Time.current - 80.years) .. (Time.current - 16.years)), - public_activity: (rand(1..100) > 30) - ) +def section(section_title) + @logger.info section_title + yield + log(' ✅') end -admin = create_user('admin@consul.dev', 'admin') -admin.create_administrator -admin.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", verified_at: Time.current, document_number: "1111111111") +def log(msg) + @logger.info "#{msg}\n" +end -moderator = create_user('mod@consul.dev', 'mod') -moderator.create_moderator +section "Creating Settings" do + Setting.create(key: 'official_level_1_name', value: 'Empleados públicos') + Setting.create(key: 'official_level_2_name', value: 'Organización Municipal') + Setting.create(key: 'official_level_3_name', value: 'Directores generales') + Setting.create(key: 'official_level_4_name', value: 'Concejales') + Setting.create(key: 'official_level_5_name', value: 'Alcaldesa') + Setting.create(key: 'max_ratio_anon_votes_on_debates', value: '50') + Setting.create(key: 'max_votes_for_debate_edit', value: '1000') + Setting.create(key: 'max_votes_for_proposal_edit', value: '1000') + Setting.create(key: 'proposal_code_prefix', value: 'MAD') + Setting.create(key: 'votes_for_proposal_success', value: '100') + Setting.create(key: 'months_to_archive_proposals', value: '12') + Setting.create(key: 'comments_body_max_length', value: '1000') -manager = create_user('manager@consul.dev', 'manager') -manager.create_manager + Setting.create(key: 'twitter_handle', value: '@consul_dev') + Setting.create(key: 'twitter_hashtag', value: '#consul_dev') + Setting.create(key: 'facebook_handle', value: 'CONSUL') + Setting.create(key: 'youtube_handle', value: 'CONSUL') + Setting.create(key: 'telegram_handle', value: 'CONSUL') + Setting.create(key: 'instagram_handle', value: 'CONSUL') + Setting.create(key: 'blog_url', value: '/blog') + Setting.create(key: 'url', value: 'http://localhost:3000') + Setting.create(key: 'org_name', value: 'CONSUL') + Setting.create(key: 'place_name', value: 'City') + Setting.create(key: 'feature.debates', value: "true") + Setting.create(key: 'feature.polls', value: "true") + Setting.create(key: 'feature.spending_proposals', value: nil) + Setting.create(key: 'feature.spending_proposal_features.voting_allowed', value: nil) + Setting.create(key: 'feature.budgets', value: "true") + Setting.create(key: 'feature.twitter_login', value: "true") + Setting.create(key: 'feature.facebook_login', value: "true") + Setting.create(key: 'feature.google_login', value: "true") + Setting.create(key: 'feature.signature_sheets', value: "true") + Setting.create(key: 'feature.legislation', value: "true") + Setting.create(key: 'feature.user.recommendations', value: "true") + Setting.create(key: 'feature.community', value: "true") + Setting.create(key: 'feature.map', value: "true") + Setting.create(key: 'per_page_code_head', value: "") + Setting.create(key: 'per_page_code_body', value: "") + Setting.create(key: 'comments_body_max_length', value: '1000') + Setting.create(key: 'mailer_from_name', value: 'CONSUL') + Setting.create(key: 'mailer_from_address', value: 'noreply@consul.dev') + Setting.create(key: 'meta_description', value: 'Citizen Participation and Open Government Application') + Setting.create(key: 'meta_keywords', value: 'citizen participation, open government') + Setting.create(key: 'verification_offices_url', value: 'http://oficinas-atencion-ciudadano.url/') + Setting.create(key: 'min_age_to_participate', value: '16') + Setting.create(key: 'proposal_improvement_path', value: nil) + Setting.create(key: 'map_latitude', value: 51.48) + Setting.create(key: 'map_longitude', value: 0.0) + Setting.create(key: 'map_zoom', value: 10) +end -valuator = create_user('valuator@consul.dev', 'valuator') -valuator.create_valuator -valuator.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", verified_at: Time.current, document_number: "2111111111") +section "Creating Geozones" do + Geozone.create(name: "city") + Geozone.create(name: "Existent District", census_code: "01") + ('A'..'Z').each { |i| Geozone.create(name: "District #{i}", external_code: i.ord, census_code: i.ord) } +end -poll_officer = create_user('poll_officer@consul.dev', 'Paul O. Fisher') -poll_officer.create_poll_officer -poll_officer.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", verified_at: Time.current, document_number: "2211111111") +section "Creating Users" do + def create_user(email, username = Faker::Name.name) + pwd = '12345678' + User.create!( + username: username, + email: email, + password: pwd, + password_confirmation: pwd, + confirmed_at: Time.current, + terms_of_service: "1", + gender: ['Male', 'Female'].sample, + date_of_birth: rand((Time.current - 80.years)..(Time.current - 16.years)), + public_activity: (rand(1..100) > 30) + ) + end -create_user('unverified@consul.dev', 'unverified') + def unique_document_number + @document_number ||= 12345678 + @document_number += 1 + "#{@document_number}#{[*'A'..'Z'].sample}" + end -level_2 = create_user('leveltwo@consul.dev', 'level 2') -level_2.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_number: "2222222222", document_type: "1") + admin = create_user('admin@consul.dev', 'admin') + admin.create_administrator + admin.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", + verified_at: Time.current, document_number: unique_document_number) -verified = create_user('verified@consul.dev', 'verified') -verified.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", verified_at: Time.current, document_number: "3333333333") + moderator = create_user('mod@consul.dev', 'mod') + moderator.create_moderator -(1..10).each do |i| - org_name = Faker::Company.name - org_user = create_user("org#{i}@consul.dev", org_name) - org_responsible_name = Faker::Name.name - org = org_user.create_organization(name: org_name, responsible_name: org_responsible_name) + manager = create_user('manager@consul.dev', 'manager') + manager.create_manager - verified = [true, false].sample - if verified - org.verify - else - org.reject + valuator = create_user('valuator@consul.dev', 'valuator') + valuator.create_valuator + valuator.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", + verified_at: Time.current, document_number: unique_document_number) + + poll_officer = create_user('poll_officer@consul.dev', 'Paul O. Fisher') + poll_officer.create_poll_officer + poll_officer.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", + verified_at: Time.current, document_number: unique_document_number) + + poll_officer2 = create_user('poll_officer2@consul.dev', 'Pauline M. Espinosa') + poll_officer2.create_poll_officer + poll_officer2.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", + verified_at: Time.current, document_number: unique_document_number) + + create_user('unverified@consul.dev', 'unverified') + + level_2 = create_user('leveltwo@consul.dev', 'level 2') + level_2.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, + document_number: unique_document_number, document_type: "1") + + verified = create_user('verified@consul.dev', 'verified') + verified.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", + verified_at: Time.current, document_number: unique_document_number) + + (1..10).each do |i| + org_name = Faker::Company.name + org_user = create_user("org#{i}@consul.dev", org_name) + org_responsible_name = Faker::Name.name + org = org_user.create_organization(name: org_name, responsible_name: org_responsible_name) + + verified = [true, false].sample + if verified + org.verify + else + org.reject + end + end + + (1..5).each do |i| + official = create_user("official#{i}@consul.dev") + official.update(official_level: i, official_position: "Official position #{i}") + end + + (1..100).each do |i| + user = create_user("user#{i}@consul.dev") + level = [1, 2, 3].sample + if level >= 2 + user.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, + document_number: unique_document_number, document_type: "1", geozone: Geozone.all.sample) + end + if level == 3 + user.update(verified_at: Time.current, document_number: unique_document_number) + end end end -(1..5).each do |i| - official = create_user("official#{i}@consul.dev") - official.update(official_level: i, official_position: "Official position #{i}") +section "Creating Tags Categories" do + ActsAsTaggableOn::Tag.category.create!(name: "Asociaciones") + ActsAsTaggableOn::Tag.category.create!(name: "Cultura") + ActsAsTaggableOn::Tag.category.create!(name: "Deportes") + ActsAsTaggableOn::Tag.category.create!(name: "Derechos Sociales") + ActsAsTaggableOn::Tag.category.create!(name: "Economía") + ActsAsTaggableOn::Tag.category.create!(name: "Empleo") + ActsAsTaggableOn::Tag.category.create!(name: "Equidad") + ActsAsTaggableOn::Tag.category.create!(name: "Sostenibilidad") + ActsAsTaggableOn::Tag.category.create!(name: "Participación") + ActsAsTaggableOn::Tag.category.create!(name: "Movilidad") + ActsAsTaggableOn::Tag.category.create!(name: "Medios") + ActsAsTaggableOn::Tag.category.create!(name: "Salud") + ActsAsTaggableOn::Tag.category.create!(name: "Transparencia") + ActsAsTaggableOn::Tag.category.create!(name: "Seguridad y Emergencias") + ActsAsTaggableOn::Tag.category.create!(name: "Medio Ambiente") end -(1..100).each do |i| - user = create_user("user#{i}@consul.dev") - level = [1, 2, 3].sample - if level >= 2 - user.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_number: Faker::Number.number(10), document_type: "1", geozone: Geozone.reorder("RANDOM()").first) +section "Creating Debates" do + tags = Faker::Lorem.words(25) + 30.times do + author = User.all.sample + description = "
#{Faker::Lorem.paragraphs.join('
')}
" + debate = Debate.create!(author: author, + title: Faker::Lorem.sentence(3).truncate(60), + created_at: rand((Time.current - 1.week)..Time.current), + description: description, + tag_list: tags.sample(3).join(','), + geozone: Geozone.all.sample, + terms_of_service: "1") end - if level == 3 - user.update(verified_at: Time.current, document_number: Faker::Number.number(10)) + + tags = ActsAsTaggableOn::Tag.where(kind: 'category') + 30.times do + author = User.all.sample + description = "#{Faker::Lorem.paragraphs.join('
')}
" + debate = Debate.create!(author: author, + title: Faker::Lorem.sentence(3).truncate(60), + created_at: rand((Time.current - 1.week)..Time.current), + description: description, + tag_list: tags.sample(3).join(','), + geozone: Geozone.all.sample, + terms_of_service: "1") end end -org_user_ids = User.organizations.pluck(:id) -not_org_users = User.where(['users.id NOT IN(?)', org_user_ids]) - -puts " ✅" -print "Creating Tags Categories" - -ActsAsTaggableOn::Tag.category.create!(name: "Asociaciones") -ActsAsTaggableOn::Tag.category.create!(name: "Cultura") -ActsAsTaggableOn::Tag.category.create!(name: "Deportes") -ActsAsTaggableOn::Tag.category.create!(name: "Derechos Sociales") -ActsAsTaggableOn::Tag.category.create!(name: "Economía") -ActsAsTaggableOn::Tag.category.create!(name: "Empleo") -ActsAsTaggableOn::Tag.category.create!(name: "Equidad") -ActsAsTaggableOn::Tag.category.create!(name: "Sostenibilidad") -ActsAsTaggableOn::Tag.category.create!(name: "Participación") -ActsAsTaggableOn::Tag.category.create!(name: "Movilidad") -ActsAsTaggableOn::Tag.category.create!(name: "Medios") -ActsAsTaggableOn::Tag.category.create!(name: "Salud") -ActsAsTaggableOn::Tag.category.create!(name: "Transparencia") -ActsAsTaggableOn::Tag.category.create!(name: "Seguridad y Emergencias") -ActsAsTaggableOn::Tag.category.create!(name: "Medio Ambiente") - -puts " ✅" -print "Creating Debates" - -tags = Faker::Lorem.words(25) -30.times do - author = User.reorder("RANDOM()").first - description = "#{Faker::Lorem.paragraphs.join('
')}
" - debate = Debate.create!(author: author, - title: Faker::Lorem.sentence(3).truncate(60), - created_at: rand((Time.current - 1.week)..Time.current), - description: description, - tag_list: tags.sample(3).join(','), - geozone: Geozone.reorder("RANDOM()").first, - terms_of_service: "1") +section "Creating Proposals" do + tags = Faker::Lorem.words(25) + 30.times do + author = User.all.sample + description = "#{Faker::Lorem.paragraphs.join('
')}
" + proposal = Proposal.create!(author: author, + title: Faker::Lorem.sentence(3).truncate(60), + question: Faker::Lorem.sentence(3) + "?", + summary: Faker::Lorem.sentence(3), + responsible_name: Faker::Name.name, + external_url: Faker::Internet.url, + description: description, + created_at: rand((Time.current - 1.week)..Time.current), + tag_list: tags.sample(3).join(','), + geozone: Geozone.all.sample, + terms_of_service: "1") + end end -tags = ActsAsTaggableOn::Tag.where(kind: 'category') -30.times do - author = User.reorder("RANDOM()").first - description = "#{Faker::Lorem.paragraphs.join('
')}
" - debate = Debate.create!(author: author, - title: Faker::Lorem.sentence(3).truncate(60), - created_at: rand((Time.current - 1.week)..Time.current), - description: description, - tag_list: tags.sample(3).join(','), - geozone: Geozone.reorder("RANDOM()").first, - terms_of_service: "1") +section "Creating Archived Proposals" do + tags = Faker::Lorem.words(25) + 5.times do + author = User.all.sample + description = "#{Faker::Lorem.paragraphs.join('
')}
" + proposal = Proposal.create!(author: author, + title: Faker::Lorem.sentence(3).truncate(60), + question: Faker::Lorem.sentence(3) + "?", + summary: Faker::Lorem.sentence(3), + responsible_name: Faker::Name.name, + external_url: Faker::Internet.url, + description: description, + tag_list: tags.sample(3).join(','), + geozone: Geozone.all.sample, + terms_of_service: "1", + created_at: Setting["months_to_archive_proposals"].to_i.months.ago) + end end -puts " ✅" -print "Creating Proposals" +section "Creating Successful Proposals" do + tags = Faker::Lorem.words(25) + 10.times do + author = User.all.sample + description = "#{Faker::Lorem.paragraphs.join('
')}
" + proposal = Proposal.create!(author: author, + title: Faker::Lorem.sentence(3).truncate(60), + question: Faker::Lorem.sentence(3) + "?", + summary: Faker::Lorem.sentence(3), + responsible_name: Faker::Name.name, + external_url: Faker::Internet.url, + description: description, + created_at: rand((Time.current - 1.week)..Time.current), + tag_list: tags.sample(3).join(','), + geozone: Geozone.all.sample, + terms_of_service: "1", + cached_votes_up: Setting["votes_for_proposal_success"]) + end -tags = Faker::Lorem.words(25) -30.times do - author = User.reorder("RANDOM()").first - description = "#{Faker::Lorem.paragraphs.join('
')}
" - proposal = Proposal.create!(author: author, - title: Faker::Lorem.sentence(3).truncate(60), - question: Faker::Lorem.sentence(3) + "?", - summary: Faker::Lorem.sentence(3), - responsible_name: Faker::Name.name, - external_url: Faker::Internet.url, - description: description, - created_at: rand((Time.current - 1.week)..Time.current), - tag_list: tags.sample(3).join(','), - geozone: Geozone.reorder("RANDOM()").first, - terms_of_service: "1") + tags = ActsAsTaggableOn::Tag.where(kind: 'category') + 30.times do + author = User.all.sample + description = "#{Faker::Lorem.paragraphs.join('
')}
" + proposal = Proposal.create!(author: author, + title: Faker::Lorem.sentence(3).truncate(60), + question: Faker::Lorem.sentence(3) + "?", + summary: Faker::Lorem.sentence(3), + responsible_name: Faker::Name.name, + external_url: Faker::Internet.url, + description: description, + created_at: rand((Time.current - 1.week)..Time.current), + tag_list: tags.sample(3).join(','), + geozone: Geozone.all.sample, + terms_of_service: "1") + end end -puts " ✅" -print "Creating Archived Proposals" - -tags = Faker::Lorem.words(25) -5.times do - author = User.reorder("RANDOM()").first - description = "#{Faker::Lorem.paragraphs.join('
')}
" - proposal = Proposal.create!(author: author, - title: Faker::Lorem.sentence(3).truncate(60), - question: Faker::Lorem.sentence(3) + "?", - summary: Faker::Lorem.sentence(3), - responsible_name: Faker::Name.name, - external_url: Faker::Internet.url, - description: description, - tag_list: tags.sample(3).join(','), - geozone: Geozone.reorder("RANDOM()").first, - terms_of_service: "1", - created_at: Setting["months_to_archive_proposals"].to_i.months.ago) +section "Commenting Debates" do + 100.times do + author = User.all.sample + debate = Debate.all.sample + Comment.create!(user: author, + created_at: rand(debate.created_at..Time.current), + commentable: debate, + body: Faker::Lorem.sentence) + end end -puts " ✅" -print "Creating Successful Proposals" - -tags = Faker::Lorem.words(25) -10.times do - author = User.reorder("RANDOM()").first - description = "#{Faker::Lorem.paragraphs.join('
')}
" - proposal = Proposal.create!(author: author, - title: Faker::Lorem.sentence(3).truncate(60), - question: Faker::Lorem.sentence(3) + "?", - summary: Faker::Lorem.sentence(3), - responsible_name: Faker::Name.name, - external_url: Faker::Internet.url, - description: description, - created_at: rand((Time.current - 1.week)..Time.current), - tag_list: tags.sample(3).join(','), - geozone: Geozone.reorder("RANDOM()").first, - terms_of_service: "1", - cached_votes_up: Setting["votes_for_proposal_success"]) +section "Commenting Proposals" do + 100.times do + author = User.all.sample + proposal = Proposal.all.sample + Comment.create!(user: author, + created_at: rand(proposal.created_at..Time.current), + commentable: proposal, + body: Faker::Lorem.sentence) + end end -tags = ActsAsTaggableOn::Tag.where(kind: 'category') -30.times do - author = User.reorder("RANDOM()").first - description = "#{Faker::Lorem.paragraphs.join('
')}
" - proposal = Proposal.create!(author: author, - title: Faker::Lorem.sentence(3).truncate(60), - question: Faker::Lorem.sentence(3) + "?", - summary: Faker::Lorem.sentence(3), - responsible_name: Faker::Name.name, - external_url: Faker::Internet.url, - description: description, - created_at: rand((Time.current - 1.week)..Time.current), - tag_list: tags.sample(3).join(','), - geozone: Geozone.reorder("RANDOM()").first, - terms_of_service: "1") +section "Commenting Comments" do + 200.times do + author = User.all.sample + parent = Comment.all.sample + Comment.create!(user: author, + created_at: rand(parent.created_at..Time.current), + commentable_id: parent.commentable_id, + commentable_type: parent.commentable_type, + body: Faker::Lorem.sentence, + parent: parent) + end end -puts " ✅" -print "Commenting Debates" +section "Voting Debates, Proposals & Comments" do + not_org_users = User.where(['users.id NOT IN(?)', User.organizations.pluck(:id)]) + 100.times do + voter = not_org_users.level_two_or_three_verified.all.sample + vote = [true, false].sample + debate = Debate.all.sample + debate.vote_by(voter: voter, vote: vote) + end -100.times do - author = User.reorder("RANDOM()").first - debate = Debate.reorder("RANDOM()").first - Comment.create!(user: author, - created_at: rand(debate.created_at..Time.current), - commentable: debate, - body: Faker::Lorem.sentence) + 100.times do + voter = not_org_users.all.sample + vote = [true, false].sample + comment = Comment.all.sample + comment.vote_by(voter: voter, vote: vote) + end + + 100.times do + voter = not_org_users.level_two_or_three_verified.all.sample + proposal = Proposal.all.sample + proposal.vote_by(voter: voter, vote: true) + end end -puts " ✅" -print "Commenting Proposals" +section "Flagging Debates & Comments" do + 40.times do + debate = Debate.all.sample + flagger = User.where(["users.id <> ?", debate.author_id]).all.sample + Flag.flag(flagger, debate) + end -100.times do - author = User.reorder("RANDOM()").first - proposal = Proposal.reorder("RANDOM()").first - Comment.create!(user: author, - created_at: rand(proposal.created_at..Time.current), - commentable: proposal, - body: Faker::Lorem.sentence) + 40.times do + comment = Comment.all.sample + flagger = User.where(["users.id <> ?", comment.user_id]).all.sample + Flag.flag(flagger, comment) + end + + 40.times do + proposal = Proposal.all.sample + flagger = User.where(["users.id <> ?", proposal.author_id]).all.sample + Flag.flag(flagger, proposal) + end end -puts " ✅" -print "Commenting Comments" - -200.times do - author = User.reorder("RANDOM()").first - parent = Comment.reorder("RANDOM()").first - Comment.create!(user: author, - created_at: rand(parent.created_at..Time.current), - commentable_id: parent.commentable_id, - commentable_type: parent.commentable_type, - body: Faker::Lorem.sentence, - parent: parent) -end - -puts " ✅" -print "Voting Debates, Proposals & Comments" - -100.times do - voter = not_org_users.level_two_or_three_verified.reorder("RANDOM()").first - vote = [true, false].sample - debate = Debate.reorder("RANDOM()").first - debate.vote_by(voter: voter, vote: vote) -end - -100.times do - voter = not_org_users.reorder("RANDOM()").first - vote = [true, false].sample - comment = Comment.reorder("RANDOM()").first - comment.vote_by(voter: voter, vote: vote) -end - -100.times do - voter = not_org_users.level_two_or_three_verified.reorder("RANDOM()").first - proposal = Proposal.reorder("RANDOM()").first - proposal.vote_by(voter: voter, vote: true) -end - -puts " ✅" -print "Flagging Debates & Comments" - -40.times do - debate = Debate.reorder("RANDOM()").first - flagger = User.where(["users.id <> ?", debate.author_id]).reorder("RANDOM()").first - Flag.flag(flagger, debate) -end - -40.times do - comment = Comment.reorder("RANDOM()").first - flagger = User.where(["users.id <> ?", comment.user_id]).reorder("RANDOM()").first - Flag.flag(flagger, comment) -end - -40.times do - proposal = Proposal.reorder("RANDOM()").first - flagger = User.where(["users.id <> ?", proposal.author_id]).reorder("RANDOM()").first - Flag.flag(flagger, proposal) -end - -puts " ✅" -print "Creating Spending Proposals" - +section "Creating Spending Proposals" do tags = Faker::Lorem.words(10) - 60.times do - geozone = Geozone.reorder("RANDOM()").first - author = User.reorder("RANDOM()").first + geozone = Geozone.all.sample + author = User.all.sample description = "#{Faker::Lorem.paragraphs.join('
')}
" feasible_explanation = "#{Faker::Lorem.paragraphs.join('
')}
" valuation_finished = [true, false].sample @@ -365,295 +382,374 @@ tags = Faker::Lorem.words(10) price: rand(1000000), terms_of_service: "1") end - -puts " ✅" -print "Creating Valuation Assignments" - -(1..17).to_a.sample.times do - SpendingProposal.reorder("RANDOM()").first.valuators << valuator.valuator end -puts " ✅" -print "Creating Budgets" +section "Creating Valuation Assignments" do + (1..17).to_a.sample.times do + SpendingProposal.all.sample.valuators << Valuator.first + end +end -Budget::PHASES.each_with_index do |phase, i| - descriptions = Hash[Budget::PHASES.map do |p| - ["description_#{p}", - "#{Faker::Lorem.paragraphs(2).join('
')}
"] - end] - budget = Budget.create!( - descriptions.merge( - name: (Date.current - 10 + i).to_s, - currency_symbol: "€", - phase: phase +section "Creating Budgets" do + Budget::PHASES.each_with_index do |phase, i| + descriptions = Hash[Budget::PHASES.map do |p| + ["description_#{p}", + "#{Faker::Lorem.paragraphs(2).join('
')}
"] + end] + budget = Budget.create!( + descriptions.merge( + name: (Date.current - 10 + i).to_s, + currency_symbol: "€", + phase: phase + ) ) - ) - (1..([1, 2, 3].sample)).each do |i| - group = budget.groups.create!(name: "#{Faker::StarWars.planet} #{i}") + (1..([1, 2, 3].sample)).each do |k| + group = budget.groups.create!(name: "#{Faker::StarWars.planet} #{k}") - geozones = Geozone.reorder("RANDOM()").limit([2, 5, 6, 7].sample) - geozones.each do |geozone| - group.headings << group.headings.create!(name: "#{geozone.name} #{i}", - price: rand(1..100) * 100000, - population: rand(1..50) * 10000) + geozones = Geozone.reorder("RANDOM()").limit([2, 5, 6, 7].sample) + geozones.each do |geozone| + group.headings << group.headings.create!(name: "#{geozone.name} #{k}", + price: rand(1..100) * 100000, + population: rand(1..50) * 10000) + end end end end -puts " ✅" -print "Creating Investments" -tags = Faker::Lorem.words(10) -100.times do - heading = Budget::Heading.reorder("RANDOM()").first +section "Creating Investments" do + tags = Faker::Lorem.words(10) + 100.times do + heading = Budget::Heading.all.sample - investment = Budget::Investment.create!( - author: User.reorder("RANDOM()").first, - heading: heading, - group: heading.group, - budget: heading.group.budget, - title: Faker::Lorem.sentence(3).truncate(60), - external_url: Faker::Internet.url, - description: "#{Faker::Lorem.paragraphs.join('
')}
", - created_at: rand((Time.current - 1.week)..Time.current), - feasibility: %w{undecided unfeasible feasible feasible feasible feasible}.sample, - unfeasibility_explanation: Faker::Lorem.paragraph, - valuation_finished: [false, true].sample, - tag_list: tags.sample(3).join(','), - price: rand(1..100) * 100000, - terms_of_service: "1" - ) -end - -puts " ✅" -print "Balloting Investments" -Budget.balloting.last.investments.each do |investment| - investment.update(selected: true, feasibility: "feasible") -end - -puts " ✅" -print "Winner Investments" - -budget = Budget.where(phase: "finished").last -100.times do - heading = budget.headings.reorder("RANDOM()").first - investment = Budget::Investment.create!( - author: User.reorder("RANDOM()").first, - heading: heading, - group: heading.group, - budget: heading.group.budget, - title: Faker::Lorem.sentence(3).truncate(60), - external_url: Faker::Internet.url, - description: "#{Faker::Lorem.paragraphs.join('
')}
", - created_at: rand((Time.current - 1.week)..Time.current), - feasibility: "feasible", - valuation_finished: true, - selected: true, - price: rand(10000..heading.price), - terms_of_service: "1" - ) -end -budget.headings.each do |heading| - Budget::Result.new(budget, heading).calculate_winners -end - -puts " ✅" -print "Creating Valuation Assignments" - -(1..50).to_a.sample.times do - Budget::Investment.reorder("RANDOM()").first.valuators << valuator.valuator -end - -puts " ✅" -print "Ignoring flags in Debates, comments & proposals" - -Debate.flagged.reorder("RANDOM()").limit(10).each(&:ignore_flag) -Comment.flagged.reorder("RANDOM()").limit(30).each(&:ignore_flag) -Proposal.flagged.reorder("RANDOM()").limit(10).each(&:ignore_flag) - -puts " ✅" -print "Hiding debates, comments & proposals" - -Comment.with_hidden.flagged.reorder("RANDOM()").limit(30).each(&:hide) -Debate.with_hidden.flagged.reorder("RANDOM()").limit(5).each(&:hide) -Proposal.with_hidden.flagged.reorder("RANDOM()").limit(10).each(&:hide) - -puts " ✅" -print "Confirming hiding in debates, comments & proposals" - -Comment.only_hidden.flagged.reorder("RANDOM()").limit(10).each(&:confirm_hide) -Debate.only_hidden.flagged.reorder("RANDOM()").limit(5).each(&:confirm_hide) -Proposal.only_hidden.flagged.reorder("RANDOM()").limit(5).each(&:confirm_hide) - -puts " ✅" -print "Creating banners" - -Proposal.last(3).each do |proposal| - title = Faker::Lorem.sentence(word_count = 3) - description = Faker::Lorem.sentence(word_count = 12) - banner = Banner.create!(title: title, - description: description, - style: ["banner-style banner-style-one", "banner-style banner-style-two", - "banner-style banner-style-three"].sample, - image: ["banner-img banner-img-one", "banner-img banner-img-two", - "banner-img banner-img-three"].sample, - target_url: Rails.application.routes.url_helpers.proposal_path(proposal), - post_started_at: rand((Time.current - 1.week)..(Time.current - 1.day)), - post_ended_at: rand((Time.current - 1.day)..(Time.current + 1.week)), - created_at: rand((Time.current - 1.week)..Time.current)) -end - -puts " ✅" -print "Creating proposal notifications" - -100.times do |i| - ProposalNotification.create!(title: "Proposal notification title #{i}", - body: "Proposal notification body #{i}", - author: User.reorder("RANDOM()").first, - proposal: Proposal.reorder("RANDOM()").first) -end - -puts " ✅" -print "Creating polls" - -puts " ✅" -print "Active Polls" -(1..3).each do |i| - poll = Poll.create(name: "Active Poll #{i}", - starts_at: 1.month.ago, - ends_at: 1.month.from_now, - geozone_restricted: false) -end -(1..5).each do |i| - poll = Poll.create(name: "Active Poll #{i}", - starts_at: 1.month.ago, - ends_at: 1.month.from_now, - geozone_restricted: true, - geozones: Geozone.reorder("RANDOM()").limit(3)) -end - -puts " ✅" -print "Upcoming Poll" -poll = Poll.create(name: "Upcoming Poll", - starts_at: 1.month.from_now, - ends_at: 2.months.from_now) - -puts " ✅" -print "Expired Poll" -poll = Poll.create(name: "Expired Poll", - starts_at: 2.months.ago, - ends_at: 1.month.ago) - -puts " ✅" -print "Creating Poll Questions" - -50.times do - poll = Poll.reorder("RANDOM()").first - author = User.reorder("RANDOM()").first - description = "#{Faker::Lorem.paragraphs.join('
')}
" - open_at = rand(2.months.ago..2.months.from_now) - question = Poll::Question.create!(author: author, - title: Faker::Lorem.sentence(3).truncate(60), - description: description, - valid_answers: Faker::Lorem.words((2..7).to_a.sample).join(', '), - poll: poll) -end - -puts " ✅" -print "Creating Poll Booths" -30.times.each_with_index do |i| - Poll::Booth.create(name: "Booth #{i}", polls: [Poll.all.sample]) -end - -puts " ✅" -print "Creating Booth Assignments" -Poll::Booth.all.each do |booth| - Poll::BoothAssignment.create(booth: booth, poll: Poll.all.sample) -end - -puts " ✅" -print "Creating Poll Officer Assignments" -(1..15).to_a.sample.times do |i| - Poll::BoothAssignment.all.sample(i).each do |booth_assignment| - Poll::OfficerAssignment.create(officer: poll_officer.poll_officer, - booth_assignment: booth_assignment, - date: booth_assignment.poll.starts_at) + investment = Budget::Investment.create!( + author: User.all.sample, + heading: heading, + group: heading.group, + budget: heading.group.budget, + title: Faker::Lorem.sentence(3).truncate(60), + external_url: Faker::Internet.url, + description: "#{Faker::Lorem.paragraphs.join('
')}
", + created_at: rand((Time.current - 1.week)..Time.current), + feasibility: %w{undecided unfeasible feasible feasible feasible feasible}.sample, + unfeasibility_explanation: Faker::Lorem.paragraph, + valuation_finished: [false, true].sample, + tag_list: tags.sample(3).join(','), + price: rand(1..100) * 100000, + terms_of_service: "1" + ) end end -puts " ✅" -print "Creating Poll Questions from Proposals" - -3.times do - proposal = Proposal.reorder("RANDOM()").first - poll = Poll.current.first - question = Poll::Question.create(valid_answers: "Yes, No", poll: poll) - question.copy_attributes_from_proposal(proposal) - question.save! -end - -puts " ✅" -print "Creating Successful Proposals" - -10.times do - proposal = Proposal.reorder("RANDOM()").first - poll = Poll.current.first - question = Poll::Question.create(valid_answers: "Yes, No", poll: poll) - question.copy_attributes_from_proposal(proposal) - question.save! -end - -puts " ✅" -print "Commenting Poll Questions" - -30.times do - author = User.reorder("RANDOM()").first - question = Poll::Question.reorder("RANDOM()").first - Comment.create!(user: author, - created_at: rand(question.created_at..Time.current), - commentable: question, - body: Faker::Lorem.sentence) -end - -puts " ✅" -print "Creating Poll Voters" - -10.times do - poll = Poll.all.sample - user = User.level_two_verified.sample - Poll::Voter.create(poll: poll, user: user) -end - -puts " ✅" -print "Creating legislation processes" - -5.times do - process = ::Legislation::Process.create!(title: Faker::Lorem.sentence(3).truncate(60), - description: Faker::Lorem.paragraphs.join("\n\n"), - summary: Faker::Lorem.paragraph, - additional_info: Faker::Lorem.paragraphs.join("\n\n"), - start_date: Date.current - 3.days, - end_date: Date.current + 3.days, - debate_start_date: Date.current - 3.days, - debate_end_date: Date.current - 1.day, - draft_publication_date: Date.current + 1.day, - allegations_start_date: Date.current + 2.days, - allegations_end_date: Date.current + 3.days, - result_publication_date: Date.current + 4.days, - debate_phase_enabled: true, - allegations_phase_enabled: true, - draft_publication_enabled: true, - result_publication_enabled: true, - published: true - ) -end - -::Legislation::Process.all.each do |process| - (1..3).each do |i| - version = process.draft_versions.create!(title: "Version #{i}", - body: Faker::Lorem.paragraphs.join("\n\n")) +section "Balloting Investments" do + Budget.balloting.last.investments.each do |investment| + investment.update(selected: true, feasibility: "feasible") end end -puts " ✅" -puts "All dev seeds created successfuly 👍" +section "Winner Investments" do + budget = Budget.where(phase: "finished").last + 100.times do + heading = budget.headings.all.sample + investment = Budget::Investment.create!( + author: User.all.sample, + heading: heading, + group: heading.group, + budget: heading.group.budget, + title: Faker::Lorem.sentence(3).truncate(60), + external_url: Faker::Internet.url, + description: "#{Faker::Lorem.paragraphs.join('
')}
", + created_at: rand((Time.current - 1.week)..Time.current), + feasibility: "feasible", + valuation_finished: true, + selected: true, + price: rand(10000..heading.price), + terms_of_service: "1" + ) + end + budget.headings.each do |heading| + Budget::Result.new(budget, heading).calculate_winners + end +end + +section "Creating Valuation Assignments" do + (1..50).to_a.sample.times do + Budget::Investment.all.sample.valuators << Valuator.first + end +end + +section "Ignoring flags in Debates, comments & proposals" do + Debate.flagged.reorder("RANDOM()").limit(10).each(&:ignore_flag) + Comment.flagged.reorder("RANDOM()").limit(30).each(&:ignore_flag) + Proposal.flagged.reorder("RANDOM()").limit(10).each(&:ignore_flag) +end + +section "Hiding debates, comments & proposals" do + Comment.with_hidden.flagged.reorder("RANDOM()").limit(30).each(&:hide) + Debate.with_hidden.flagged.reorder("RANDOM()").limit(5).each(&:hide) + Proposal.with_hidden.flagged.reorder("RANDOM()").limit(10).each(&:hide) +end + +section "Confirming hiding in debates, comments & proposals" do + Comment.only_hidden.flagged.reorder("RANDOM()").limit(10).each(&:confirm_hide) + Debate.only_hidden.flagged.reorder("RANDOM()").limit(5).each(&:confirm_hide) + Proposal.only_hidden.flagged.reorder("RANDOM()").limit(5).each(&:confirm_hide) +end + +section "Creating banners" do + Proposal.last(3).each do |proposal| + title = Faker::Lorem.sentence(word_count = 3) + description = Faker::Lorem.sentence(word_count = 12) + banner = Banner.create!(title: title, + description: description, + style: ["banner-style banner-style-one", "banner-style banner-style-two", + "banner-style banner-style-three"].sample, + image: ["banner-img banner-img-one", "banner-img banner-img-two", + "banner-img banner-img-three"].sample, + target_url: Rails.application.routes.url_helpers.proposal_path(proposal), + post_started_at: rand((Time.current - 1.week)..(Time.current - 1.day)), + post_ended_at: rand((Time.current - 1.day)..(Time.current + 1.week)), + created_at: rand((Time.current - 1.week)..Time.current)) + end +end + +section "Creating proposal notifications" do + 100.times do |i| + ProposalNotification.create!(title: "Proposal notification title #{i}", + body: "Proposal notification body #{i}", + author: User.all.sample, + proposal: Proposal.all.sample) + end +end + +section "Creating polls" do + + Poll.create(name: "Current Poll", + # TODO: Uncomment when Poll get slugs + # slug: "current-poll", + starts_at: 7.days.ago, + ends_at: 7.days.from_now, + geozone_restricted: false) + + Poll.create(name: "Current Poll Geozone Restricted", + # TODO: Uncomment when Poll get slugs + # slug: "current-poll-geozone-restricted", + starts_at: 5.days.ago, + ends_at: 5.days.from_now, + geozone_restricted: true, + geozones: Geozone.reorder("RANDOM()").limit(3)) + + Poll.create(name: "Incoming Poll", + # TODO: Uncomment when Poll get slugs + # slug: "incoming-poll", + starts_at: 1.month.from_now, + ends_at: 2.months.from_now) + + Poll.create(name: "Recounting Poll", + # TODO: Uncomment when Poll get slugs + # slug: "recounting-poll", + starts_at: 15.days.ago, + ends_at: 2.days.ago) + + Poll.create(name: "Expired Poll without Stats & Results", + # TODO: Uncomment when Poll get slugs + # slug: "expired-poll-without-stats-and-results", + starts_at: 2.months.ago, + ends_at: 1.month.ago) + + Poll.create(name: "Expired Poll with Stats & Results", + # TODO: Uncomment when Poll get slugs + # slug: "expired-poll-with-stats-and-results", + starts_at: 2.months.ago, + ends_at: 1.month.ago, + results_enabled: true, + stats_enabled: true) +end + +section "Creating Poll Questions & Answers" do + Poll.all.each do |poll| + (1..4).to_a.sample.times do + question = Poll::Question.create!(author: User.all.sample, + title: Faker::Lorem.sentence(3).truncate(60) + '?', + poll: poll) + Faker::Lorem.words((2..4).to_a.sample).each do |answer| + Poll::Question::Answer.create!(question: question, + title: answer.capitalize, + description: "#{Faker::Lorem.paragraphs.join('
')}
") + end + end + end +end + +section "Creating Poll Booths & BoothAssignments" do + 20.times do |i| + Poll::Booth.create(name: "Booth #{i}", location: Faker::Address.street_address, polls: [Poll.all.sample]) + end +end + +section "Creating Poll Shifts for Poll Officers" do + Poll.all.each do |poll| + Poll::BoothAssignment.where(poll: poll).each do |booth_assignment| + Poll::Officer.all.each do |poll_officer| + { + vote_collection: (poll.starts_at.to_datetime..poll.ends_at.to_datetime), + recount_scrutiny: (poll.ends_at.to_datetime..poll.ends_at.to_datetime + Poll::RECOUNT_DURATION) + }.each do |task_name, task_dates| + task_dates.each do |shift_date| + Poll::Shift.create(booth: booth_assignment.booth, + officer: poll_officer, + date: shift_date, + officer_name: poll_officer.name, + officer_email: poll_officer.email, + task: task_name) + end + end + end + end + end +end + +section "Commenting Poll Questions" do + 30.times do + author = User.all.sample + question = Poll::Question.all.sample + Comment.create!(user: author, + created_at: rand(question.created_at..Time.current), + commentable: question, + body: Faker::Lorem.sentence) + end +end + +section "Creating Poll Voters" do + + def vote_poll_on_booth(user, poll) + Poll::Voter.create!(document_type: user.document_type, + document_number: user.document_number, + user: user, + poll: poll, + origin: 'booth', + officer: Poll::Officer.all.sample) + end + + def vote_poll_on_web(user, poll) + randomly_answer_questions(poll, user) + Poll::Voter.create!(document_type: user.document_type, + document_number: user.document_number, + user: user, + poll: poll, + origin: 'web', + token: SecureRandom.hex(32)) + end + + def randomly_answer_questions(poll, user) + poll.questions.each do |question| + next unless [true, false].sample + Poll::Answer.create!(question_id: question.id, author: user, answer: question.question_answers.sample.title) + end + end + + (Poll.expired + Poll.current + Poll.recounting).uniq.each do |poll| + level_two_verified_users = User.level_two_verified + level_two_verified_users = level_two_verified_users.where(geozone_id: poll.geozone_ids) if poll.geozone_restricted? + user_groups = level_two_verified_users.in_groups(2) + user_groups.first.each { |user| vote_poll_on_booth(user, poll) } + user_groups.second.compact.each { |user| vote_poll_on_web(user, poll) } + end +end + +section "Creating Poll Recounts" do + Poll.all.each do |poll| + poll.booth_assignments.each do |booth_assignment| + officer_assignment = poll.officer_assignments.first + author = Poll::Officer.first.user + + Poll::Recount.create!(officer_assignment: officer_assignment, + booth_assignment: booth_assignment, + author: author, + date: poll.ends_at, + white_amount: rand(0..10), + null_amount: rand(0..10), + total_amount: rand(100..9999), + origin: "booth") + end + end +end + +section "Creating Poll Results" do + Poll.all.each do |poll| + poll.booth_assignments.each do |booth_assignment| + officer_assignment = poll.officer_assignments.first + author = Poll::Officer.first.user + + poll.questions.each do |question| + question.question_answers.each do |answer| + Poll::PartialResult.create!(officer_assignment: officer_assignment, + booth_assignment: booth_assignment, + date: Date.current, + question: question, + answer: answer.title, + author: author, + amount: rand(999), + origin: "booth") + end + end + end + end +end + +section "Creating Poll Questions from Proposals" do + 3.times do + proposal = Proposal.all.sample + poll = Poll.current.first + question = Poll::Question.create(poll: poll) + Faker::Lorem.words((2..4).to_a.sample).each do |answer| + Poll::Question::Answer.create!(question: question, title: answer.capitalize, description: Faker::ChuckNorris.fact) + end + question.copy_attributes_from_proposal(proposal) + question.save! + end +end + +section "Creating Successful Proposals" do + 10.times do + proposal = Proposal.all.sample + poll = Poll.current.first + question = Poll::Question.create(poll: poll) + Faker::Lorem.words((2..4).to_a.sample).each do |answer| + Poll::Question::Answer.create!(question: question, title: answer.capitalize, description: Faker::ChuckNorris.fact) + end + question.copy_attributes_from_proposal(proposal) + question.save! + end +end + +section "Creating legislation processes" do + 5.times do + process = ::Legislation::Process.create!(title: Faker::Lorem.sentence(3).truncate(60), + description: Faker::Lorem.paragraphs.join("\n\n"), + summary: Faker::Lorem.paragraph, + additional_info: Faker::Lorem.paragraphs.join("\n\n"), + start_date: Date.current - 3.days, + end_date: Date.current + 3.days, + debate_start_date: Date.current - 3.days, + debate_end_date: Date.current - 1.day, + draft_publication_date: Date.current + 1.day, + allegations_start_date: Date.current + 2.days, + allegations_end_date: Date.current + 3.days, + result_publication_date: Date.current + 4.days, + debate_phase_enabled: true, + allegations_phase_enabled: true, + draft_publication_enabled: true, + result_publication_enabled: true, + published: true) + end + + ::Legislation::Process.all.each do |process| + (1..3).each do |i| + version = process.draft_versions.create!(title: "Version #{i}", + body: Faker::Lorem.paragraphs.join("\n\n")) + end + end +end + +log "All dev seeds created successfuly 👍" diff --git a/db/migrate/20170627113331_create_images.rb b/db/migrate/20170627113331_create_images.rb new file mode 100644 index 000000000..66567845a --- /dev/null +++ b/db/migrate/20170627113331_create_images.rb @@ -0,0 +1,14 @@ +class CreateImages < ActiveRecord::Migration + def up + create_table :images do |t| + t.references :imageable, polymorphic: true, index: true + t.string :title, limit: 80 + t.timestamps null: false + end + add_attachment :images, :attachment + end + + def down + remove_attachment :images, :attachment + end +end diff --git a/db/migrate/20170805132736_create_map_locations.rb b/db/migrate/20170805132736_create_map_locations.rb new file mode 100644 index 000000000..a75820d54 --- /dev/null +++ b/db/migrate/20170805132736_create_map_locations.rb @@ -0,0 +1,11 @@ +class CreateMapLocations < ActiveRecord::Migration + def change + create_table :map_locations do |t| + t.float :latitude + t.float :longitude + t.integer :zoom + t.integer :proposal_id, index: true + t.integer :investment_id, index: true + end + end +end diff --git a/db/migrate/20170911110109_add_user_id_to_images.rb b/db/migrate/20170911110109_add_user_id_to_images.rb new file mode 100644 index 000000000..31467acee --- /dev/null +++ b/db/migrate/20170911110109_add_user_id_to_images.rb @@ -0,0 +1,5 @@ +class AddUserIdToImages < ActiveRecord::Migration + def change + add_reference :images, :user, index: true, foreign_key: true + end +end diff --git a/db/migrate/20170913101029_add_proposals_phase_to_legislation_processes.rb b/db/migrate/20170913101029_add_proposals_phase_to_legislation_processes.rb new file mode 100644 index 000000000..b3ecfe3f1 --- /dev/null +++ b/db/migrate/20170913101029_add_proposals_phase_to_legislation_processes.rb @@ -0,0 +1,7 @@ +class AddProposalsPhaseToLegislationProcesses < ActiveRecord::Migration + def change + add_column :legislation_processes, :proposals_phase_start_date, :date + add_column :legislation_processes, :proposals_phase_end_date, :date + add_column :legislation_processes, :proposals_phase_enabled, :boolean + end +end diff --git a/db/migrate/20170913130803_add_proposals_description_to_legislation_processes.rb b/db/migrate/20170913130803_add_proposals_description_to_legislation_processes.rb new file mode 100644 index 000000000..d5e4f9c5d --- /dev/null +++ b/db/migrate/20170913130803_add_proposals_description_to_legislation_processes.rb @@ -0,0 +1,5 @@ +class AddProposalsDescriptionToLegislationProcesses < ActiveRecord::Migration + def change + add_column :legislation_processes, :proposals_description, :text + end +end diff --git a/db/migrate/20170914102634_create_legislation_proposals.rb b/db/migrate/20170914102634_create_legislation_proposals.rb new file mode 100644 index 000000000..defe9f1dd --- /dev/null +++ b/db/migrate/20170914102634_create_legislation_proposals.rb @@ -0,0 +1,32 @@ +class CreateLegislationProposals < ActiveRecord::Migration + def change + create_table :legislation_proposals do |t| + t.references :legislation_process, index: true, foreign_key: true + t.string :title, limit: 80 + t.text :description + t.string :question + t.string :external_url + t.integer :author_id + t.datetime :hidden_at + t.integer :flags_count, default: 0 + t.datetime :ignored_flag_at + t.integer :cached_votes_up, default: 0 + t.integer :comments_count, default: 0 + t.datetime :confirmed_hide_at + t.integer :hot_score, limit: 8, default: 0 + t.integer :confidence_score, default: 0 + t.string :responsible_name, limit: 60 + t.text :summary + t.string :video_url + t.tsvector :tsv + t.integer :geozone_id + t.datetime :retired_at + t.string :retired_reason + t.text :retired_explanation + t.integer :community_id + + t.datetime :created_at, null: false + t.datetime :updated_at, null: false + end + end +end diff --git a/db/migrate/20170915101519_add_legislation_proposals_count_to_tags.rb b/db/migrate/20170915101519_add_legislation_proposals_count_to_tags.rb new file mode 100644 index 000000000..9ce6ace89 --- /dev/null +++ b/db/migrate/20170915101519_add_legislation_proposals_count_to_tags.rb @@ -0,0 +1,6 @@ +class AddLegislationProposalsCountToTags < ActiveRecord::Migration + def change + add_column :tags, "legislation/proposals_count", :integer, default: 0 + add_index :tags, "legislation/proposals_count" + end +end diff --git a/db/migrate/20170922101247_add_legislation_processes_count_to_tags.rb b/db/migrate/20170922101247_add_legislation_processes_count_to_tags.rb new file mode 100644 index 000000000..698a66af6 --- /dev/null +++ b/db/migrate/20170922101247_add_legislation_processes_count_to_tags.rb @@ -0,0 +1,6 @@ +class AddLegislationProcessesCountToTags < ActiveRecord::Migration + def change + add_column :tags, "legislation/processes_count", :integer, default: 0 + add_index :tags, "legislation/processes_count" + end +end diff --git a/db/migrate/20170927110953_add_shift_task.rb b/db/migrate/20170927110953_add_shift_task.rb new file mode 100644 index 000000000..8adf23dd1 --- /dev/null +++ b/db/migrate/20170927110953_add_shift_task.rb @@ -0,0 +1,5 @@ +class AddShiftTask < ActiveRecord::Migration + def change + add_column :poll_shifts, :task, :integer, null: false, default: 0 + end +end diff --git a/db/migrate/20170928132402_add_summary_and_description_to_polls.rb b/db/migrate/20170928132402_add_summary_and_description_to_polls.rb new file mode 100644 index 000000000..6fb965346 --- /dev/null +++ b/db/migrate/20170928132402_add_summary_and_description_to_polls.rb @@ -0,0 +1,6 @@ +class AddSummaryAndDescriptionToPolls < ActiveRecord::Migration + def change + add_column :polls, :summary, :text + add_column :polls, :description, :text + end +end diff --git a/db/migrate/20171002103314_add_poll_shift_task_index.rb b/db/migrate/20171002103314_add_poll_shift_task_index.rb new file mode 100644 index 000000000..d15275556 --- /dev/null +++ b/db/migrate/20171002103314_add_poll_shift_task_index.rb @@ -0,0 +1,7 @@ +class AddPollShiftTaskIndex < ActiveRecord::Migration + def change + remove_index "poll_shifts", name: "index_poll_shifts_on_booth_id_and_officer_id" + add_index :poll_shifts, :task + add_index :poll_shifts, [:booth_id, :officer_id, :task], unique: true + end +end diff --git a/db/migrate/20171002121658_add_origin_to_poll_voters.rb b/db/migrate/20171002121658_add_origin_to_poll_voters.rb new file mode 100644 index 000000000..845c1b774 --- /dev/null +++ b/db/migrate/20171002121658_add_origin_to_poll_voters.rb @@ -0,0 +1,5 @@ +class AddOriginToPollVoters < ActiveRecord::Migration + def change + add_column :poll_voters, :origin, :string + end +end diff --git a/db/migrate/20171002122312_create_poll_recount.rb b/db/migrate/20171002122312_create_poll_recount.rb new file mode 100644 index 000000000..807f1c84e --- /dev/null +++ b/db/migrate/20171002122312_create_poll_recount.rb @@ -0,0 +1,24 @@ +class CreatePollRecount < ActiveRecord::Migration + def change + create_table :poll_recounts do |t| + t.integer :author_id + t.string :origin + t.date :date + t.integer :booth_assignment_id + t.integer :officer_assignment_id + t.text :officer_assignment_id_log, default: "" + t.text :author_id_log, default: "" + t.integer :white_amount + t.text :white_amount_log, default: "" + t.integer :null_amount + t.text :null_amount_log, default: "" + t.integer :total_amount + t.text :total_amount_log, default: "" + end + + add_index :poll_recounts, :booth_assignment_id + add_index :poll_recounts, :officer_assignment_id + add_foreign_key :poll_recounts, :poll_booth_assignments, column: :booth_assignment_id + add_foreign_key :poll_recounts, :poll_officer_assignments, column: :officer_assignment_id + end +end diff --git a/db/migrate/20171002133547_remove_poll_white_null_total_results.rb b/db/migrate/20171002133547_remove_poll_white_null_total_results.rb new file mode 100644 index 000000000..5fff82ef3 --- /dev/null +++ b/db/migrate/20171002133547_remove_poll_white_null_total_results.rb @@ -0,0 +1,16 @@ +class RemovePollWhiteNullTotalResults < ActiveRecord::Migration + def change + remove_index :poll_null_results, column: [:booth_assignment_id] + remove_index :poll_null_results, column: [:officer_assignment_id] + + remove_index :poll_white_results, column: [:booth_assignment_id] + remove_index :poll_white_results, column: [:officer_assignment_id] + + remove_index :poll_total_results, column: [:booth_assignment_id] + remove_index :poll_total_results, column: [:officer_assignment_id] + + drop_table :poll_null_results + drop_table :poll_total_results + drop_table :poll_white_results + end +end diff --git a/db/migrate/20171002191347_add_default_to_recount_amounts.rb b/db/migrate/20171002191347_add_default_to_recount_amounts.rb new file mode 100644 index 000000000..b90e86aae --- /dev/null +++ b/db/migrate/20171002191347_add_default_to_recount_amounts.rb @@ -0,0 +1,7 @@ +class AddDefaultToRecountAmounts < ActiveRecord::Migration + def change + change_column_default :poll_recounts, :white_amount, 0 + change_column_default :poll_recounts, :null_amount, 0 + change_column_default :poll_recounts, :total_amount, 0 + end +end diff --git a/db/migrate/20171003095936_remove_officer_assigment_composed_index.rb b/db/migrate/20171003095936_remove_officer_assigment_composed_index.rb new file mode 100644 index 000000000..874672f84 --- /dev/null +++ b/db/migrate/20171003095936_remove_officer_assigment_composed_index.rb @@ -0,0 +1,5 @@ +class RemoveOfficerAssigmentComposedIndex < ActiveRecord::Migration + def change + remove_index "poll_officer_assignments", name: "index_poll_officer_assignments_on_officer_id_and_date" + end +end diff --git a/db/migrate/20171003143034_add_comments_count_to_polls.rb b/db/migrate/20171003143034_add_comments_count_to_polls.rb new file mode 100644 index 000000000..675acae3f --- /dev/null +++ b/db/migrate/20171003143034_add_comments_count_to_polls.rb @@ -0,0 +1,7 @@ +class AddCommentsCountToPolls < ActiveRecord::Migration + def change + add_column :polls, :comments_count, :integer, default: 0 + add_column :polls, :author_id, :integer + add_column :polls, :hidden_at, :datetime + end +end diff --git a/db/migrate/20171003170029_remove_description_from_poll_questions.rb b/db/migrate/20171003170029_remove_description_from_poll_questions.rb new file mode 100644 index 000000000..31e1b9578 --- /dev/null +++ b/db/migrate/20171003170029_remove_description_from_poll_questions.rb @@ -0,0 +1,5 @@ +class RemoveDescriptionFromPollQuestions < ActiveRecord::Migration + def change + remove_column :poll_questions, :description + end +end diff --git a/db/migrate/20171003212958_add_date_to_poll_shift_composed_index.rb b/db/migrate/20171003212958_add_date_to_poll_shift_composed_index.rb new file mode 100644 index 000000000..b59a859c1 --- /dev/null +++ b/db/migrate/20171003212958_add_date_to_poll_shift_composed_index.rb @@ -0,0 +1,7 @@ +class AddDateToPollShiftComposedIndex < ActiveRecord::Migration + def change + remove_index "poll_shifts", name: "index_poll_shifts_on_booth_id_and_officer_id_and_task" + remove_index "poll_shifts", name: "index_poll_shifts_on_task" + add_index :poll_shifts, [:booth_id, :officer_id, :date, :task], unique: true + end +end diff --git a/db/migrate/20171003223152_add_officer_to_poll_voter.rb b/db/migrate/20171003223152_add_officer_to_poll_voter.rb new file mode 100644 index 000000000..99f9cd3e3 --- /dev/null +++ b/db/migrate/20171003223152_add_officer_to_poll_voter.rb @@ -0,0 +1,5 @@ +class AddOfficerToPollVoter < ActiveRecord::Migration + def change + add_column :poll_voters, :officer_id, :integer + end +end diff --git a/db/migrate/20171004025903_create_poll_question_answers.rb b/db/migrate/20171004025903_create_poll_question_answers.rb new file mode 100644 index 000000000..834421f5f --- /dev/null +++ b/db/migrate/20171004025903_create_poll_question_answers.rb @@ -0,0 +1,9 @@ +class CreatePollQuestionAnswers < ActiveRecord::Migration + def change + create_table :poll_question_answers do |t| + t.string :title + t.text :description + t.references :poll_question, index: true, foreign_key: true + end + end +end diff --git a/db/migrate/20171004151553_rename_poll_question_id_to_question_id.rb b/db/migrate/20171004151553_rename_poll_question_id_to_question_id.rb new file mode 100644 index 000000000..c53298bfb --- /dev/null +++ b/db/migrate/20171004151553_rename_poll_question_id_to_question_id.rb @@ -0,0 +1,5 @@ +class RenamePollQuestionIdToQuestionId < ActiveRecord::Migration + def change + rename_column :poll_question_answers, :poll_question_id, :question_id + end +end diff --git a/db/migrate/20171004210108_create_poll_question_answer_videos.rb b/db/migrate/20171004210108_create_poll_question_answer_videos.rb new file mode 100644 index 000000000..7cce33b29 --- /dev/null +++ b/db/migrate/20171004210108_create_poll_question_answer_videos.rb @@ -0,0 +1,11 @@ +class CreatePollQuestionAnswerVideos < ActiveRecord::Migration + def change + create_table :poll_question_answer_videos do |t| + t.string :title + t.string :url + t.integer :answer_id, index: true + end + + add_foreign_key :poll_question_answer_videos, :poll_question_answers, column: :answer_id + end +end diff --git a/db/migrate/20171006145053_add_token_to_poll_voters.rb b/db/migrate/20171006145053_add_token_to_poll_voters.rb new file mode 100644 index 000000000..5d07f5065 --- /dev/null +++ b/db/migrate/20171006145053_add_token_to_poll_voters.rb @@ -0,0 +1,5 @@ +class AddTokenToPollVoters < ActiveRecord::Migration + def change + add_column :poll_voters, :token, :string + end +end diff --git a/db/migrate/20171010143623_add_given_order_to_poll_question_answers.rb b/db/migrate/20171010143623_add_given_order_to_poll_question_answers.rb new file mode 100644 index 000000000..6161e55e4 --- /dev/null +++ b/db/migrate/20171010143623_add_given_order_to_poll_question_answers.rb @@ -0,0 +1,5 @@ +class AddGivenOrderToPollQuestionAnswers < ActiveRecord::Migration + def change + add_column :poll_question_answers, :given_order, :integer, default: 1 + end +end diff --git a/db/migrate/20171017221546_remove_poll_question_valid_answers.rb b/db/migrate/20171017221546_remove_poll_question_valid_answers.rb new file mode 100644 index 000000000..e4c1ebb11 --- /dev/null +++ b/db/migrate/20171017221546_remove_poll_question_valid_answers.rb @@ -0,0 +1,5 @@ +class RemovePollQuestionValidAnswers < ActiveRecord::Migration + def change + remove_column :poll_questions, :valid_answers + end +end diff --git a/db/migrate/20171019095042_add_most_voted_to_poll_question_answer.rb b/db/migrate/20171019095042_add_most_voted_to_poll_question_answer.rb new file mode 100644 index 000000000..e4650643b --- /dev/null +++ b/db/migrate/20171019095042_add_most_voted_to_poll_question_answer.rb @@ -0,0 +1,5 @@ +class AddMostVotedToPollQuestionAnswer < ActiveRecord::Migration + def change + add_column :poll_question_answers, :most_voted, :boolean, default: false + end +end diff --git a/db/migrate/20171020163240_add_results_and_stats_to_polls.rb b/db/migrate/20171020163240_add_results_and_stats_to_polls.rb new file mode 100644 index 000000000..af6f82aaa --- /dev/null +++ b/db/migrate/20171020163240_add_results_and_stats_to_polls.rb @@ -0,0 +1,6 @@ +class AddResultsAndStatsToPolls < ActiveRecord::Migration + def change + add_column :polls, :results_enabled, :boolean, default: false + add_column :polls, :stats_enabled, :boolean, default: false + end +end diff --git a/db/migrate/20171025142440_add_cached_votes_to_legislation_proposals.rb b/db/migrate/20171025142440_add_cached_votes_to_legislation_proposals.rb new file mode 100644 index 000000000..92544ddb6 --- /dev/null +++ b/db/migrate/20171025142440_add_cached_votes_to_legislation_proposals.rb @@ -0,0 +1,6 @@ +class AddCachedVotesToLegislationProposals < ActiveRecord::Migration + def change + add_column :legislation_proposals, :cached_votes_total, :integer, default: 0 + add_column :legislation_proposals, :cached_votes_down, :integer, default: 0 + end +end diff --git a/db/migrate/20171115164152_add_time_zone_to_default_datetimes.rb b/db/migrate/20171115164152_add_time_zone_to_default_datetimes.rb new file mode 100644 index 000000000..13bc51264 --- /dev/null +++ b/db/migrate/20171115164152_add_time_zone_to_default_datetimes.rb @@ -0,0 +1,6 @@ +class AddTimeZoneToDefaultDatetimes < ActiveRecord::Migration + def change + change_column_default :users, :password_changed_at, DateTime.new(2015, 1, 1, 1, 1, 1, '+00:00') + change_column_default :locks, :locked_until, DateTime.new(2000, 1, 1, 1, 1, 1, '+00:00') + end +end diff --git a/db/schema.rb b/db/schema.rb index 240abcdaa..f2dd62428 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170918231410) do +ActiveRecord::Schema.define(version: 20171115164152) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -388,6 +388,22 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree + create_table "images", force: :cascade do |t| + t.integer "imageable_id" + t.string "imageable_type" + t.string "title", limit: 80 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "attachment_file_name" + t.string "attachment_content_type" + t.integer "attachment_file_size" + t.datetime "attachment_updated_at" + t.integer "user_id" + end + + add_index "images", ["imageable_type", "imageable_id"], name: "index_images_on_imageable_type_and_imageable_id", using: :btree + add_index "images", ["user_id"], name: "index_images_on_user_id", using: :btree + create_table "legacy_legislations", force: :cascade do |t| t.string "title" t.text "body" @@ -470,6 +486,10 @@ ActiveRecord::Schema.define(version: 20170918231410) do t.boolean "draft_publication_enabled", default: false t.boolean "result_publication_enabled", default: false t.boolean "published", default: true + t.date "proposals_phase_start_date" + t.date "proposals_phase_end_date" + t.boolean "proposals_phase_enabled" + t.text "proposals_description" end add_index "legislation_processes", ["allegations_end_date"], name: "index_legislation_processes_on_allegations_end_date", using: :btree @@ -482,6 +502,38 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "legislation_processes", ["result_publication_date"], name: "index_legislation_processes_on_result_publication_date", using: :btree add_index "legislation_processes", ["start_date"], name: "index_legislation_processes_on_start_date", using: :btree + create_table "legislation_proposals", force: :cascade do |t| + t.integer "legislation_process_id" + t.string "title", limit: 80 + t.text "description" + t.string "question" + t.string "external_url" + t.integer "author_id" + t.datetime "hidden_at" + t.integer "flags_count", default: 0 + t.datetime "ignored_flag_at" + t.integer "cached_votes_up", default: 0 + t.integer "comments_count", default: 0 + t.datetime "confirmed_hide_at" + t.integer "hot_score", limit: 8, default: 0 + t.integer "confidence_score", default: 0 + t.string "responsible_name", limit: 60 + t.text "summary" + t.string "video_url" + t.tsvector "tsv" + t.integer "geozone_id" + t.datetime "retired_at" + t.string "retired_reason" + t.text "retired_explanation" + t.integer "community_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "cached_votes_total", default: 0 + t.integer "cached_votes_down", default: 0 + end + + add_index "legislation_proposals", ["legislation_process_id"], name: "index_legislation_proposals_on_legislation_process_id", using: :btree + create_table "legislation_question_options", force: :cascade do |t| t.integer "legislation_question_id" t.string "value" @@ -520,7 +572,7 @@ ActiveRecord::Schema.define(version: 20170918231410) do create_table "locks", force: :cascade do |t| t.integer "user_id" t.integer "tries", default: 0 - t.datetime "locked_until", default: '2000-01-01 00:01:01', null: false + t.datetime "locked_until", default: '2000-01-01 01:01:01', null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end @@ -533,6 +585,17 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "managers", ["user_id"], name: "index_managers_on_user_id", using: :btree + create_table "map_locations", force: :cascade do |t| + t.float "latitude" + t.float "longitude" + t.integer "zoom" + t.integer "proposal_id" + t.integer "investment_id" + end + + add_index "map_locations", ["investment_id"], name: "index_map_locations_on_investment_id", using: :btree + add_index "map_locations", ["proposal_id"], name: "index_map_locations_on_proposal_id", using: :btree + create_table "moderators", force: :cascade do |t| t.integer "user_id" end @@ -586,21 +649,6 @@ ActiveRecord::Schema.define(version: 20170918231410) do t.string "location" end - create_table "poll_null_results", force: :cascade do |t| - t.integer "author_id" - t.integer "amount" - t.string "origin" - t.date "date" - t.integer "booth_assignment_id" - t.integer "officer_assignment_id" - t.text "amount_log", default: "" - t.text "officer_assignment_id_log", default: "" - t.text "author_id_log", default: "" - end - - add_index "poll_null_results", ["booth_assignment_id"], name: "index_poll_null_results_on_booth_assignment_id", using: :btree - add_index "poll_null_results", ["officer_assignment_id"], name: "index_poll_null_results_on_officer_assignment_id", using: :btree - create_table "poll_officer_assignments", force: :cascade do |t| t.integer "booth_assignment_id" t.integer "officer_id" @@ -612,7 +660,6 @@ ActiveRecord::Schema.define(version: 20170918231410) do end add_index "poll_officer_assignments", ["booth_assignment_id"], name: "index_poll_officer_assignments_on_booth_assignment_id", using: :btree - add_index "poll_officer_assignments", ["officer_id", "date"], name: "index_poll_officer_assignments_on_officer_id_and_date", using: :btree add_index "poll_officer_assignments", ["officer_id"], name: "index_poll_officer_assignments_on_officer_id", using: :btree create_table "poll_officers", force: :cascade do |t| @@ -642,14 +689,30 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "poll_partial_results", ["origin"], name: "index_poll_partial_results_on_origin", using: :btree add_index "poll_partial_results", ["question_id"], name: "index_poll_partial_results_on_question_id", using: :btree + create_table "poll_question_answer_videos", force: :cascade do |t| + t.string "title" + t.string "url" + t.integer "answer_id" + end + + add_index "poll_question_answer_videos", ["answer_id"], name: "index_poll_question_answer_videos_on_answer_id", using: :btree + + create_table "poll_question_answers", force: :cascade do |t| + t.string "title" + t.text "description" + t.integer "question_id" + t.integer "given_order", default: 1 + t.boolean "most_voted", default: false + end + + add_index "poll_question_answers", ["question_id"], name: "index_poll_question_answers_on_question_id", using: :btree + create_table "poll_questions", force: :cascade do |t| t.integer "proposal_id" t.integer "poll_id" t.integer "author_id" t.string "author_visible_name" t.string "title" - t.string "valid_answers" - t.text "description" t.integer "comments_count" t.datetime "hidden_at" t.datetime "created_at" @@ -663,6 +726,25 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "poll_questions", ["proposal_id"], name: "index_poll_questions_on_proposal_id", using: :btree add_index "poll_questions", ["tsv"], name: "index_poll_questions_on_tsv", using: :gin + create_table "poll_recounts", force: :cascade do |t| + t.integer "author_id" + t.string "origin" + t.date "date" + t.integer "booth_assignment_id" + t.integer "officer_assignment_id" + t.text "officer_assignment_id_log", default: "" + t.text "author_id_log", default: "" + t.integer "white_amount", default: 0 + t.text "white_amount_log", default: "" + t.integer "null_amount", default: 0 + t.text "null_amount_log", default: "" + t.integer "total_amount", default: 0 + t.text "total_amount_log", default: "" + end + + add_index "poll_recounts", ["booth_assignment_id"], name: "index_poll_recounts_on_booth_assignment_id", using: :btree + add_index "poll_recounts", ["officer_assignment_id"], name: "index_poll_recounts_on_officer_assignment_id", using: :btree + create_table "poll_shifts", force: :cascade do |t| t.integer "booth_id" t.integer "officer_id" @@ -671,27 +753,13 @@ ActiveRecord::Schema.define(version: 20170918231410) do t.datetime "updated_at" t.string "officer_name" t.string "officer_email" + t.integer "task", default: 0, null: false end - add_index "poll_shifts", ["booth_id", "officer_id"], name: "index_poll_shifts_on_booth_id_and_officer_id", using: :btree + add_index "poll_shifts", ["booth_id", "officer_id", "date", "task"], name: "index_poll_shifts_on_booth_id_and_officer_id_and_date_and_task", unique: true, using: :btree add_index "poll_shifts", ["booth_id"], name: "index_poll_shifts_on_booth_id", using: :btree add_index "poll_shifts", ["officer_id"], name: "index_poll_shifts_on_officer_id", using: :btree - create_table "poll_total_results", force: :cascade do |t| - t.integer "author_id" - t.integer "amount" - t.string "origin" - t.date "date" - t.integer "booth_assignment_id" - t.integer "officer_assignment_id" - t.text "amount_log", default: "" - t.text "officer_assignment_id_log", default: "" - t.text "author_id_log", default: "" - end - - add_index "poll_total_results", ["booth_assignment_id"], name: "index_poll_total_results_on_booth_assignment_id", using: :btree - add_index "poll_total_results", ["officer_assignment_id"], name: "index_poll_total_results_on_officer_assignment_id", using: :btree - create_table "poll_voters", force: :cascade do |t| t.string "document_number" t.string "document_type" @@ -705,6 +773,9 @@ ActiveRecord::Schema.define(version: 20170918231410) do t.integer "answer_id" t.integer "officer_assignment_id" t.integer "user_id" + t.string "origin" + t.integer "officer_id" + t.string "token" end add_index "poll_voters", ["booth_assignment_id"], name: "index_poll_voters_on_booth_assignment_id", using: :btree @@ -714,27 +785,19 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "poll_voters", ["poll_id"], name: "index_poll_voters_on_poll_id", using: :btree add_index "poll_voters", ["user_id"], name: "index_poll_voters_on_user_id", using: :btree - create_table "poll_white_results", force: :cascade do |t| - t.integer "author_id" - t.integer "amount" - t.string "origin" - t.date "date" - t.integer "booth_assignment_id" - t.integer "officer_assignment_id" - t.text "amount_log", default: "" - t.text "officer_assignment_id_log", default: "" - t.text "author_id_log", default: "" - end - - add_index "poll_white_results", ["booth_assignment_id"], name: "index_poll_white_results_on_booth_assignment_id", using: :btree - add_index "poll_white_results", ["officer_assignment_id"], name: "index_poll_white_results_on_officer_assignment_id", using: :btree - create_table "polls", force: :cascade do |t| t.string "name" t.datetime "starts_at" t.datetime "ends_at" t.boolean "published", default: false t.boolean "geozone_restricted", default: false + t.text "summary" + t.text "description" + t.integer "comments_count", default: 0 + t.integer "author_id" + t.datetime "hidden_at" + t.boolean "results_enabled", default: false + t.boolean "stats_enabled", default: false end add_index "polls", ["starts_at", "ends_at"], name: "index_polls_on_starts_at_and_ends_at", using: :btree @@ -894,16 +957,20 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree create_table "tags", force: :cascade do |t| - t.string "name", limit: 40 - t.integer "taggings_count", default: 0 - t.integer "debates_count", default: 0 - t.integer "proposals_count", default: 0 - t.integer "spending_proposals_count", default: 0 + t.string "name", limit: 40 + t.integer "taggings_count", default: 0 + t.integer "debates_count", default: 0 + t.integer "proposals_count", default: 0 + t.integer "spending_proposals_count", default: 0 t.string "kind" - t.integer "budget/investments_count", default: 0 + t.integer "budget/investments_count", default: 0 + t.integer "legislation/proposals_count", default: 0 + t.integer "legislation/processes_count", default: 0 end add_index "tags", ["debates_count"], name: "index_tags_on_debates_count", using: :btree + add_index "tags", ["legislation/processes_count"], name: "index_tags_on_legislation/processes_count", using: :btree + add_index "tags", ["legislation/proposals_count"], name: "index_tags_on_legislation/proposals_count", using: :btree add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree add_index "tags", ["proposals_count"], name: "index_tags_on_proposals_count", using: :btree add_index "tags", ["spending_proposals_count"], name: "index_tags_on_spending_proposals_count", using: :btree @@ -975,7 +1042,7 @@ ActiveRecord::Schema.define(version: 20170918231410) do t.boolean "email_digest", default: true t.boolean "email_on_direct_message", default: true t.boolean "official_position_badge", default: false - t.datetime "password_changed_at", default: '2015-01-01 00:01:01', null: false + t.datetime "password_changed_at", default: '2015-01-01 01:01:01', null: false t.boolean "created_from_signature", default: false t.integer "failed_email_digests_count", default: 0 t.text "former_users_data_log", default: "" @@ -1079,7 +1146,9 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_foreign_key "geozones_polls", "geozones" add_foreign_key "geozones_polls", "polls" add_foreign_key "identities", "users" + add_foreign_key "images", "users" add_foreign_key "legislation_draft_versions", "legislation_processes" + add_foreign_key "legislation_proposals", "legislation_processes" add_foreign_key "locks", "users" add_foreign_key "managers", "users" add_foreign_key "moderators", "users" @@ -1087,19 +1156,19 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_foreign_key "organizations", "users" add_foreign_key "poll_answers", "poll_questions", column: "question_id" add_foreign_key "poll_booth_assignments", "polls" - add_foreign_key "poll_null_results", "poll_booth_assignments", column: "booth_assignment_id" - add_foreign_key "poll_null_results", "poll_officer_assignments", column: "officer_assignment_id" add_foreign_key "poll_officer_assignments", "poll_booth_assignments", column: "booth_assignment_id" add_foreign_key "poll_partial_results", "poll_booth_assignments", column: "booth_assignment_id" add_foreign_key "poll_partial_results", "poll_officer_assignments", column: "officer_assignment_id" add_foreign_key "poll_partial_results", "poll_questions", column: "question_id" add_foreign_key "poll_partial_results", "users", column: "author_id" + add_foreign_key "poll_question_answer_videos", "poll_question_answers", column: "answer_id" + add_foreign_key "poll_question_answers", "poll_questions", column: "question_id" add_foreign_key "poll_questions", "polls" add_foreign_key "poll_questions", "proposals" add_foreign_key "poll_questions", "users", column: "author_id" + add_foreign_key "poll_recounts", "poll_booth_assignments", column: "booth_assignment_id" + add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id" add_foreign_key "poll_voters", "polls" - add_foreign_key "poll_white_results", "poll_booth_assignments", column: "booth_assignment_id" - add_foreign_key "poll_white_results", "poll_officer_assignments", column: "officer_assignment_id" add_foreign_key "proposals", "communities" add_foreign_key "users", "geozones" add_foreign_key "valuators", "users" diff --git a/db/seeds.rb b/db/seeds.rb index 96916f29a..fcfa6340c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -79,7 +79,9 @@ Setting['feature.public_stats'] = true Setting['feature.budgets'] = true Setting['feature.signature_sheets'] = true Setting['feature.legislation'] = true +Setting['feature.user.recommendations'] = true Setting['feature.community'] = true +Setting['feature.map'] = nil # Spending proposals feature flags Setting['feature.spending_proposal_features.voting_allowed'] = nil @@ -108,3 +110,8 @@ Setting['min_age_to_participate'] = 16 # Proposal improvement url path ('/more-information/proposal-improvement') Setting['proposal_improvement_path'] = nil + +# City map feature default configuration (Greenwich) +Setting['map_latitude'] = 51.48 +Setting['map_longitude'] = 0.0 +Setting['map_zoom'] = 10 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..d5399089e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +# service configuration for our database +database: + + # use the preferred version of the official Postgres image + # see https://hub.docker.com/_/postgres/ + image: postgres:9.4.5 + + # persist the database between containers by storing it in a volume + volumes: + - docker-example-postgres:/var/lib/postgresql/data + +# service configuration for our dockerized Rails app +app: + + # use the Dockerfile next to this file + build: . + + # rely on the RAILS_ENV value of the host machine + # environment: + #RAILS_ENV: $RAILS_ENV + + # makes the app container aware of the DB container + links: + - database + + # expose the port we configured Unicorn to bind to + ports: + - "3000:3000" + # map our application source code, in full, to the application root of our container + volumes: + - .:/var/www/consul diff --git a/knapsack_rspec_report.json b/knapsack_rspec_report.json index 595276b2b..5f1fc06b5 100644 --- a/knapsack_rspec_report.json +++ b/knapsack_rspec_report.json @@ -1,226 +1,227 @@ { - "spec/helpers/comments_helper_spec.rb": 0.010898828506469727, - "spec/controllers/graphql_controller_spec.rb": 0.7817962169647217, - "spec/controllers/concerns/has_orders_spec.rb": 0.09597063064575195, - "spec/features/officing/results_spec.rb": 2.6492855548858643, - "spec/models/poll/question_spec.rb": 0.09519433975219727, - "spec/features/organizations_spec.rb": 1.9025108814239502, - "spec/models/legislation/process_spec.rb": 0.09253501892089844, - "spec/lib/acts_as_paranoid_aliases_spec.rb": 0.2438969612121582, - "spec/features/officing_spec.rb": 1.4767742156982422, - "spec/lib/age_spec.rb": 0.0006227493286132812, - "spec/models/proposal_spec.rb": 5.535696983337402, - "spec/models/abilities/administrator_spec.rb": 2.2431821823120117, - "spec/models/poll/final_recount_spec.rb": 0.1787703037261963, - "spec/lib/graph_ql/query_type_creator_spec.rb": 0.012041091918945312, - "spec/models/verification/management/email_spec.rb": 0.06403493881225586, - "spec/models/flag_spec.rb": 0.46442556381225586, - "spec/features/tags/budget_investments_spec.rb": 23.748523235321045, - "spec/features/campaigns_spec.rb": 1.3289697170257568, - "spec/features/admin/activity_spec.rb": 7.763890743255615, - "spec/features/polls/questions_spec.rb": 2.61055326461792, - "spec/features/polls/polls_spec.rb": 2.313369035720825, - "spec/features/home_spec.rb": 0.9780440330505371, - "spec/models/poll/partial_result_spec.rb": 0.3302469253540039, - "spec/models/lock_spec.rb": 0.09437012672424316, - "spec/lib/graph_ql/api_types_creator_spec.rb": 0.0069005489349365234, - "spec/helpers/users_helper_spec.rb": 0.3229796886444092, - "spec/lib/local_census_spec.rb": 0.011091947555541992, - "spec/helpers/text_helper_spec.rb": 0.0005347728729248047, - "spec/customization_engine_spec.rb": 1.3630127906799316, - "spec/models/legislation/answer_spec.rb": 0.6906075477600098, - "spec/models/budget/ballot/line_spec.rb": 0.5054352283477783, - "spec/features/admin/proposals_spec.rb": 1.6710176467895508, - "spec/features/proposal_ballots_spec.rb": 0.3399386405944824, - "spec/models/site_customization/content_block_spec.rb": 0.014521121978759766, - "spec/features/admin/site_customization/content_blocks_spec.rb": 1.2890841960906982, - "spec/models/site_customization/page_spec.rb": 0.011090993881225586, - "spec/features/verification/email_spec.rb": 1.0991628170013428, - "spec/models/proposal_notification_spec.rb": 0.2569601535797119, - "spec/features/registration_form_spec.rb": 0.7285032272338867, - "spec/features/communities_spec.rb": 1.7133822441101074, - "spec/features/admin/moderators_spec.rb": 1.2922589778900146, - "spec/helpers/geozones_helper_spec.rb": 0.09812736511230469, - "spec/features/welcome_spec.rb": 1.5019774436950684, - "spec/controllers/comments_controller_spec.rb": 0.36508607864379883, - "spec/features/admin/legislation/questions_spec.rb": 3.81538724899292, - "spec/controllers/users/registrations_controller_spec.rb": 0.018311023712158203, - "spec/features/comments/debates_spec.rb": 12.265411615371704, - "spec/features/users_spec.rb": 11.05901050567627, - "spec/models/budget/group_spec.rb": 0.04957008361816406, - "spec/features/admin/poll/questions_spec.rb": 1.9041199684143066, - "spec/helpers/admin_helper_spec.rb": 0.00651097297668457, - "spec/models/abilities/organization_spec.rb": 0.24821996688842773, - "spec/features/moderation/comments_spec.rb": 6.318082332611084, - "spec/features/admin/poll/polls_spec.rb": 8.88325023651123, - "spec/models/activity_spec.rb": 0.9704892635345459, - "spec/features/verification/level_two_verification_spec.rb": 0.421832799911499, - "spec/models/poll/officer_assignment_spec.rb": 0.029267072677612305, - "spec/features/admin/verifications_spec.rb": 0.507885217666626, - "spec/mailers/mailer_spec.rb": 0.07406282424926758, - "spec/models/legislation/draft_version_spec.rb": 0.025011777877807617, - "spec/models/budget/investment_spec.rb": 9.084597826004028, - "spec/features/proposals_spec.rb": 183.71455550193787, - "spec/features/tags_spec.rb": 2.949070453643799, - "spec/features/tags/debates_spec.rb": 4.345250368118286, - "spec/features/admin/geozones_spec.rb": 1.935765027999878, - "spec/features/admin/feature_flags_spec.rb": 0.8357558250427246, - "spec/models/user_spec.rb": 2.436626434326172, - "spec/features/moderation/debates_spec.rb": 6.05112886428833, - "spec/models/legislation/annotation_spec.rb": 0.21427702903747559, - "spec/features/comments/proposals_spec.rb": 32.52879500389099, - "spec/controllers/legislation/answers_controller_spec.rb": 0.3481717109680176, - "spec/features/verification/sms_spec.rb": 1.2817349433898926, - "spec/features/admin/budget_investments_spec.rb": 16.1332266330719, - "spec/features/notifications_spec.rb": 14.857182264328003, - "spec/lib/tag_sanitizer_spec.rb": 0.0005936622619628906, - "spec/controllers/admin/api/stats_controller_spec.rb": 0.3948392868041992, - "spec/features/comments/topics_spec.rb": 29.646622896194458, - "spec/models/debate_spec.rb": 5.2278876304626465, - "spec/lib/email_digests_spec.rb": 0.6660604476928711, - "spec/models/abilities/everyone_spec.rb": 0.06328749656677246, - "spec/features/direct_messages_spec.rb": 1.3006987571716309, - "spec/features/debates_spec.rb": 28.736626386642456, - "spec/models/setting_spec.rb": 0.07938265800476074, - "spec/models/legislation/question_option_spec.rb": 0.058206796646118164, - "spec/models/verification/management/document_spec.rb": 0.013574600219726562, - "spec/models/poll/booth_spec.rb": 0.07824325561523438, - "spec/features/admin/legislation/draft_versions_spec.rb": 3.750009059906006, - "spec/features/admin/poll/officers_spec.rb": 1.4151291847229004, - "spec/features/moderation_spec.rb": 1.9578778743743896, - "spec/features/legislation/questions_spec.rb": 1.7689197063446045, - "spec/features/officing/residence_spec.rb": 0.971078634262085, - "spec/models/follow_spec.rb": 0.12199592590332031, - "spec/lib/census_api_spec.rb": 0.0019702911376953125, - "spec/models/tag_cloud_spec.rb": 1.5725350379943848, - "spec/models/budget_spec.rb": 0.2335052490234375, - "spec/features/management/localization_spec.rb": 1.1911811828613281, - "spec/features/legislation/draft_versions_spec.rb": 8.151643514633179, - "spec/models/budget/heading_spec.rb": 0.09901237487792969, - "spec/models/poll/poll_spec.rb": 0.46999382972717285, - "spec/models/custom/residence_spec.rb": 0.050164222717285156, - "spec/models/notification_spec.rb": 0.39408183097839355, - "spec/features/budgets/ballots_spec.rb": 27.406018257141113, - "spec/mailers/devise_mailer_spec.rb": 0.16486406326293945, - "spec/features/admin/debates_spec.rb": 1.546919345855713, - "spec/features/valuation/budgets_spec.rb": 0.2552778720855713, - "spec/models/abilities/common_spec.rb": 6.724466562271118, - "spec/models/residence_spec.rb": 0.24986696243286133, - "spec/features/officing/voters_spec.rb": 2.954087257385254, - "spec/models/vote_spec.rb": 1.3241477012634277, - "spec/lib/migrate_spending_proposals_to_investments_spec.rb": 1.1774518489837646, - "spec/controllers/management/users_controller_spec.rb": 0.007733821868896484, - "spec/helpers/proposals_helper_spec.rb": 0.21885180473327637, - "spec/features/ckeditor_spec.rb": 0.7726309299468994, - "spec/lib/census_caller_spec.rb": 0.009332895278930664, - "spec/features/tracks_spec.rb": 2.7082908153533936, - "spec/features/admin/budgets_spec.rb": 4.468225002288818, - "spec/features/admin/valuators_spec.rb": 1.3326430320739746, - "spec/features/admin/banners_spec.rb": 3.302579164505005, - "spec/features/account_spec.rb": 2.30243182182312, - "spec/features/budgets/budgets_spec.rb": 1.0318260192871094, - "spec/models/poll/answer_spec.rb": 0.11362218856811523, - "spec/features/comments/budget_investments_spec.rb": 16.92409658432007, - "spec/features/budgets/results_spec.rb": 2.589841365814209, - "spec/features/valuation_spec.rb": 2.126727819442749, - "spec/features/stats_spec.rb": 0.8516559600830078, - "spec/features/admin/poll/booths_spec.rb": 1.766916275024414, - "spec/models/legislation/process/phase_spec.rb": 0.0886683464050293, - "spec/models/budget/investment/milestone_spec.rb": 0.1419520378112793, - "spec/models/letter_spec.rb": 0.08197903633117676, - "spec/features/admin/stats_spec.rb": 3.6946730613708496, - "spec/models/identity_spec.rb": 0.004762887954711914, - "spec/features/verification/letter_spec.rb": 1.7480952739715576, - "spec/models/topic_spec.rb": 0.30414509773254395, - "spec/features/users_auth_spec.rb": 7.242254257202148, - "spec/lib/acts_as_taggable_on_spec.rb": 0.7477433681488037, - "spec/features/official_positions_spec.rb": 1.9427640438079834, - "spec/features/admin/newsletters_spec.rb": 0.22768402099609375, - "spec/features/admin/hidden_users_spec.rb": 1.4156956672668457, - "spec/features/comments/legislation_annotations_spec.rb": 18.616747856140137, - "spec/features/admin/site_customization/pages_spec.rb": 1.0219447612762451, - "spec/models/poll/shift_spec.rb": 0.2051677703857422, - "spec/models/geozone_spec.rb": 0.12972474098205566, - "spec/helpers/verification_helper_spec.rb": 0.0009250640869140625, - "spec/lib/cache_spec.rb": 0.06447911262512207, - "spec/features/verification/verification_path_spec.rb": 1.2300751209259033, - "spec/features/sessions_spec.rb": 0.3665180206298828, - "spec/controllers/management/base_controller_spec.rb": 0.019928932189941406, - "spec/features/verification/verified_user_spec.rb": 0.787623405456543, - "spec/models/direct_message_spec.rb": 0.49156641960144043, - "spec/features/admin/tags_spec.rb": 1.045637845993042, - "spec/features/admin/comments_spec.rb": 3.4312756061553955, - "spec/features/moderation/users_spec.rb": 1.1841027736663818, - "spec/models/budget/reclassified_vote_spec.rb": 0.22663235664367676, - "spec/features/admin/organizations_spec.rb": 3.4465878009796143, - "spec/features/proposal_notifications_spec.rb": 4.40612268447876, - "spec/features/emails_spec.rb": 13.047018051147461, - "spec/controllers/debates_controller_spec.rb": 0.3078582286834717, - "spec/features/budgets/investments_spec.rb": 126.55784440040588, - "spec/features/verification/residence_spec.rb": 1.8894774913787842, - "spec/models/abilities/moderator_spec.rb": 2.7029502391815186, - "spec/helpers/votes_helper_spec.rb": 0.363523006439209, - "spec/features/tags/proposals_spec.rb": 8.272820949554443, - "spec/models/signature_spec.rb": 1.6858570575714111, - "spec/models/legislation/process/publication_spec.rb": 0.0707387924194336, - "spec/models/community_spec.rb": 0.13965797424316406, - "spec/models/sms_spec.rb": 0.024147987365722656, - "spec/lib/graphql_spec.rb": 3.7293970584869385, - "spec/lib/tasks/communities_spec.rb": 0.17484474182128906, - "spec/features/management/proposals_spec.rb": 4.549585580825806, - "spec/models/document_spec.rb": 1.2667145729064941, - "spec/features/site_customization/content_blocks_spec.rb": 0.3020951747894287, - "spec/features/localization_spec.rb": 0.5679850578308105, - "spec/models/signature_sheet_spec.rb": 0.7970001697540283, - "spec/features/budgets/votes_spec.rb": 4.38911509513855, - "spec/features/verification/level_three_verification_spec.rb": 1.2754230499267578, - "spec/features/admin/users_spec.rb": 0.3584918975830078, - "spec/models/abilities/valuator_spec.rb": 1.1300320625305176, - "spec/models/officing/residence_spec.rb": 0.3599817752838135, - "spec/features/admin/officials_spec.rb": 0.940401554107666, - "spec/features/admin/settings_spec.rb": 0.37268495559692383, - "spec/models/ahoy/data_source_spec.rb": 0.04887723922729492, - "spec/helpers/settings_helper_spec.rb": 0.020088911056518555, - "spec/models/budget/result_spec.rb": 0.7962813377380371, - "spec/models/poll/null_result_spec.rb": 0.17995309829711914, - "spec/models/valuator_spec.rb": 0.02411341667175293, - "spec/lib/manager_authenticator_spec.rb": 0.0031435489654541016, - "spec/lib/tasks/settings_spec.rb": 0.07562613487243652, - "spec/controllers/legislation/annotations_controller_spec.rb": 0.712010383605957, - "spec/models/comment_spec.rb": 1.7274408340454102, - "spec/features/comments/legislation_questions_spec.rb": 15.219935894012451, - "spec/features/admin_spec.rb": 1.1390578746795654, - "spec/features/admin/poll/booth_assigments_spec.rb": 3.737426280975342, - "spec/controllers/pages_controller_spec.rb": 0.3043200969696045, - "spec/features/admin/administrators_spec.rb": 2.7916433811187744, - "spec/models/poll/total_result_spec.rb": 0.549537181854248, - "spec/features/management/managed_users_spec.rb": 4.38576078414917, - "spec/models/poll/officer_spec.rb": 0.49225711822509766, - "spec/features/user_invites_spec.rb": 0.21891093254089355, - "spec/helpers/application_helper_spec.rb": 0.13661718368530273, - "spec/features/management/account_spec.rb": 0.9717822074890137, - "spec/features/management/document_verifications_spec.rb": 1.0395607948303223, - "spec/features/admin/site_customization/images_spec.rb": 1.2623581886291504, - "spec/models/organization_spec.rb": 0.16587495803833008, - "spec/features/management/email_verifications_spec.rb": 0.46370506286621094, - "spec/features/legislation/processes_spec.rb": 3.2473270893096924, - "spec/features/admin/managers_spec.rb": 1.1836414337158203, - "spec/models/legislation/question_spec.rb": 0.4404168128967285, - "spec/features/management/budget_investments_spec.rb": 7.179029703140259, - "spec/features/admin/signature_sheets_spec.rb": 1.4004056453704834, - "spec/features/admin/poll/shifts_spec.rb": 2.6800806522369385, - "spec/i18n_spec.rb": 58.107173204422, - "spec/features/site_customization/custom_pages_spec.rb": 0.454498291015625, - "spec/features/admin/legislation/processes_spec.rb": 3.3492519855499268, - "spec/features/votes_spec.rb": 16.538654088974, - "spec/features/admin/budget_investment_milestones_spec.rb": 1.3747622966766357, - "spec/models/poll/white_result_spec.rb": 0.23045921325683594, - "spec/controllers/management/sessions_controller_spec.rb": 0.06758952140808105, - "spec/features/management/users_spec.rb": 2.044326066970825, - "spec/controllers/concerns/has_filters_spec.rb": 0.275907039642334, - "spec/features/moderation/proposals_spec.rb": 5.00596022605896, - "spec/lib/wysiwyg_sanitizer_spec.rb": 0.0016448497772216797, - "spec/models/budget/ballot_spec.rb": 0.6595156192779541, - "spec/models/poll/voter_spec.rb": 0.2982313632965088, - "spec/features/valuation/budget_investments_spec.rb": 6.490516185760498 + "spec/models/setting_spec.rb": 0.07869887351989746, + "spec/features/admin/managers_spec.rb": 5.029380798339844, + "spec/features/management/managed_users_spec.rb": 3.1642160415649414, + "spec/features/admin/poll/booths_spec.rb": 1.4152588844299316, + "spec/features/admin/comments_spec.rb": 3.889301061630249, + "spec/helpers/admin_helper_spec.rb": 0.005057334899902344, + "spec/models/abilities/moderator_spec.rb": 2.3274271488189697, + "spec/controllers/admin/api/stats_controller_spec.rb": 0.4249396324157715, + "spec/features/admin/organizations_spec.rb": 3.339292049407959, + "spec/features/admin/newsletters_spec.rb": 0.2460641860961914, + "spec/helpers/geozones_helper_spec.rb": 0.08249163627624512, + "spec/lib/graph_ql/api_types_creator_spec.rb": 0.006573915481567383, + "spec/features/emails_spec.rb": 18.91256046295166, + "spec/features/admin/hidden_users_spec.rb": 1.3854436874389648, + "spec/features/welcome_spec.rb": 1.1956276893615723, + "spec/features/sessions_spec.rb": 0.3943772315979004, + "spec/models/custom/residence_spec.rb": 0.07002687454223633, + "spec/models/poll/booth_spec.rb": 0.05489993095397949, + "spec/models/direct_message_spec.rb": 0.3973381519317627, + "spec/features/valuation/budget_investments_spec.rb": 7.6013023853302, + "spec/models/map_location_spec.rb": 0.12476563453674316, + "spec/models/budget/heading_spec.rb": 0.09248590469360352, + "spec/models/user_spec.rb": 2.9006423950195312, + "spec/features/admin/site_customization/content_blocks_spec.rb": 1.6733989715576172, + "spec/mailers/mailer_spec.rb": 0.08513784408569336, + "spec/models/site_customization/page_spec.rb": 0.015056133270263672, + "spec/features/management/budget_investments_spec.rb": 8.112786293029785, + "spec/features/admin/activity_spec.rb": 12.442089080810547, + "spec/features/registration_form_spec.rb": 1.0509357452392578, + "spec/controllers/legislation/annotations_controller_spec.rb": 0.8151364326477051, + "spec/lib/census_caller_spec.rb": 0.018165111541748047, + "spec/features/users_auth_spec.rb": 6.5102221965789795, + "spec/features/tags/proposals_spec.rb": 10.001718521118164, + "spec/features/account_spec.rb": 2.2510504722595215, + "spec/features/admin/users_spec.rb": 0.4342050552368164, + "spec/lib/cache_spec.rb": 0.057682037353515625, + "spec/features/valuation_spec.rb": 1.3436784744262695, + "spec/models/budget/investment_spec.rb": 12.89230751991272, + "spec/lib/migrate_spending_proposals_to_investments_spec.rb": 0.904367208480835, + "spec/helpers/settings_helper_spec.rb": 0.02300858497619629, + "spec/helpers/application_helper_spec.rb": 0.09152626991271973, + "spec/models/legislation/draft_version_spec.rb": 0.020322084426879883, + "spec/models/legislation/question_spec.rb": 0.3402721881866455, + "spec/models/document_spec.rb": 1.3238348960876465, + "spec/models/poll/question_spec.rb": 0.12588191032409668, + "spec/features/admin/poll/polls_spec.rb": 11.77881646156311, + "spec/lib/manager_authenticator_spec.rb": 0.006296873092651367, + "spec/features/admin/debates_spec.rb": 1.688420295715332, + "spec/features/moderation/debates_spec.rb": 5.343512773513794, + "spec/controllers/debates_controller_spec.rb": 0.40573883056640625, + "spec/models/tag_cloud_spec.rb": 1.6984672546386719, + "spec/models/budget/investment/milestone_spec.rb": 0.15051603317260742, + "spec/models/proposal_notification_spec.rb": 0.2914905548095703, + "spec/features/budgets/investments_spec.rb": 93.5263159275055, + "spec/i18n_spec.rb": 96.26275777816772, + "spec/models/community_spec.rb": 0.16270899772644043, + "spec/controllers/graphql_controller_spec.rb": 0.5831413269042969, + "spec/models/legislation/annotation_spec.rb": 0.16232728958129883, + "spec/lib/acts_as_taggable_on_spec.rb": 0.5747356414794922, + "spec/lib/census_api_spec.rb": 0.0021581649780273438, + "spec/features/moderation/comments_spec.rb": 6.70704984664917, + "spec/models/poll/voter_spec.rb": 0.32018303871154785, + "spec/features/proposal_notifications_spec.rb": 3.906450033187866, + "spec/models/budget/result_spec.rb": 0.8468267917633057, + "spec/helpers/users_helper_spec.rb": 0.25751638412475586, + "spec/features/valuation/budgets_spec.rb": 0.2564871311187744, + "spec/controllers/users/registrations_controller_spec.rb": 0.022383689880371094, + "spec/controllers/management/base_controller_spec.rb": 0.06711888313293457, + "spec/features/admin/officials_spec.rb": 0.893528938293457, + "spec/features/comments/topics_spec.rb": 29.998314142227173, + "spec/features/users_spec.rb": 11.885858297348022, + "spec/models/topic_spec.rb": 0.27634167671203613, + "spec/models/follow_spec.rb": 0.1256728172302246, + "spec/lib/local_census_spec.rb": 0.005529880523681641, + "spec/features/verification/sms_spec.rb": 1.5214743614196777, + "spec/helpers/comments_helper_spec.rb": 0.010879278182983398, + "spec/models/valuator_spec.rb": 0.02650904655456543, + "spec/features/proposal_ballots_spec.rb": 0.3937220573425293, + "spec/features/proposals_spec.rb": 142.48229122161865, + "spec/features/legislation/processes_spec.rb": 2.863476514816284, + "spec/features/ckeditor_spec.rb": 0.8433480262756348, + "spec/models/letter_spec.rb": 0.0695810317993164, + "spec/features/admin/budget_investments_spec.rb": 18.484699964523315, + "spec/models/officing/residence_spec.rb": 0.3402073383331299, + "spec/controllers/concerns/has_orders_spec.rb": 0.1844041347503662, + "spec/features/admin/legislation/processes_spec.rb": 4.020649433135986, + "spec/features/management/users_spec.rb": 2.288966178894043, + "spec/lib/tasks/communities_spec.rb": 0.15353775024414062, + "spec/models/abilities/organization_spec.rb": 0.24793481826782227, + "spec/features/polls/polls_spec.rb": 2.591568946838379, + "spec/features/communities_spec.rb": 1.6137127876281738, + "spec/models/legislation/process/phase_spec.rb": 0.07121586799621582, + "spec/features/officing_spec.rb": 0.979363203048706, + "spec/features/site_customization/custom_pages_spec.rb": 0.5588700771331787, + "spec/features/comments/legislation_questions_spec.rb": 14.133169889450073, + "spec/features/organizations_spec.rb": 0.46280837059020996, + "spec/controllers/legislation/answers_controller_spec.rb": 0.39082813262939453, + "spec/models/image_spec.rb": 7.636544466018677, + "spec/features/management/account_spec.rb": 1.150636911392212, + "spec/models/abilities/common_spec.rb": 5.959435701370239, + "spec/features/comments/debates_spec.rb": 13.69457721710205, + "spec/models/poll/shift_spec.rb": 0.19109749794006348, + "spec/features/site_customization/content_blocks_spec.rb": 0.3058288097381592, + "spec/models/poll/recount_spec.rb": 0.1983809471130371, + "spec/features/verification/level_two_verification_spec.rb": 0.4596068859100342, + "spec/features/verification/level_three_verification_spec.rb": 1.456559658050537, + "spec/lib/tasks/settings_spec.rb": 0.04654407501220703, + "spec/features/admin/budget_investment_milestones_spec.rb": 1.3974273204803467, + "spec/features/management/localization_spec.rb": 1.1653187274932861, + "spec/features/admin/tags_spec.rb": 1.0751111507415771, + "spec/features/officing/results_spec.rb": 1.2672057151794434, + "spec/features/admin/poll/booth_assigments_spec.rb": 4.1742753982543945, + "spec/models/poll/officer_assignment_spec.rb": 0.024514198303222656, + "spec/controllers/management/sessions_controller_spec.rb": 0.07244610786437988, + "spec/features/admin/signature_sheets_spec.rb": 1.4268932342529297, + "spec/models/debate_spec.rb": 4.550540924072266, + "spec/features/comments/proposals_spec.rb": 25.726442337036133, + "spec/models/poll/partial_result_spec.rb": 0.32181620597839355, + "spec/features/admin/legislation/draft_versions_spec.rb": 3.4613990783691406, + "spec/models/budget_spec.rb": 0.14807415008544922, + "spec/models/sms_spec.rb": 0.018825769424438477, + "spec/features/admin/proposals_spec.rb": 1.837270975112915, + "spec/models/geozone_spec.rb": 0.11852264404296875, + "spec/features/admin/banners_spec.rb": 3.0584604740142822, + "spec/models/legislation/process/publication_spec.rb": 0.06270265579223633, + "spec/lib/graph_ql/query_type_creator_spec.rb": 0.009456157684326172, + "spec/features/moderation_spec.rb": 1.001516342163086, + "spec/features/campaigns_spec.rb": 0.8359789848327637, + "spec/features/admin/verifications_spec.rb": 0.6421175003051758, + "spec/features/localization_spec.rb": 0.756089448928833, + "spec/features/admin/poll/questions_spec.rb": 41.59848093986511, + "spec/features/tags/debates_spec.rb": 3.4022486209869385, + "spec/helpers/text_helper_spec.rb": 0.0006229877471923828, + "spec/features/admin/moderators_spec.rb": 1.3467354774475098, + "spec/models/flag_spec.rb": 0.5202171802520752, + "spec/mailers/devise_mailer_spec.rb": 0.2588930130004883, + "spec/features/user_invites_spec.rb": 0.18819189071655273, + "spec/features/legislation/draft_versions_spec.rb": 9.352471828460693, + "spec/features/home_spec.rb": 3.0868682861328125, + "spec/features/budgets/results_spec.rb": 2.4918482303619385, + "spec/features/budgets/votes_spec.rb": 4.285862922668457, + "spec/features/comments/budget_investments_spec.rb": 16.1397545337677, + "spec/features/admin/stats_spec.rb": 2.678718090057373, + "spec/features/polls/questions_spec.rb": 2.594414472579956, + "spec/features/admin/poll/shifts_spec.rb": 4.629284143447876, + "spec/helpers/votes_helper_spec.rb": 0.31733107566833496, + "spec/models/ahoy/data_source_spec.rb": 0.04695439338684082, + "spec/models/residence_spec.rb": 0.20260858535766602, + "spec/features/admin_spec.rb": 0.6963987350463867, + "spec/controllers/comments_controller_spec.rb": 0.2683417797088623, + "spec/lib/age_spec.rb": 0.0007379055023193359, + "spec/models/legislation/answer_spec.rb": 0.14532899856567383, + "spec/features/tags_spec.rb": 3.0131027698516846, + "spec/features/admin/valuators_spec.rb": 1.0099408626556396, + "spec/models/notification_spec.rb": 0.37938618659973145, + "spec/views/welcome/index.html.erb_spec.rb": 0.1471250057220459, + "spec/customization_engine_spec.rb": 1.5587348937988281, + "spec/models/poll/officer_spec.rb": 0.2980079650878906, + "spec/features/budgets/ballots_spec.rb": 25.24861741065979, + "spec/controllers/concerns/has_filters_spec.rb": 0.1412961483001709, + "spec/features/moderation/proposals_spec.rb": 5.947849273681641, + "spec/features/management/document_verifications_spec.rb": 0.9574480056762695, + "spec/features/legislation/questions_spec.rb": 1.605849027633667, + "spec/models/proposal_spec.rb": 5.872406482696533, + "spec/models/legislation/question_option_spec.rb": 0.0395960807800293, + "spec/features/budgets/budgets_spec.rb": 0.8722023963928223, + "spec/lib/email_digests_spec.rb": 0.440814733505249, + "spec/features/official_positions_spec.rb": 1.5717194080352783, + "spec/features/officing/residence_spec.rb": 0.9819045066833496, + "spec/features/officing/voters_spec.rb": 2.078903913497925, + "spec/features/direct_messages_spec.rb": 1.6070659160614014, + "spec/models/abilities/everyone_spec.rb": 0.059804677963256836, + "spec/lib/acts_as_paranoid_aliases_spec.rb": 0.33096909523010254, + "spec/features/debates_spec.rb": 32.84718298912048, + "spec/features/votes_spec.rb": 18.217467069625854, + "spec/models/activity_spec.rb": 1.0154414176940918, + "spec/controllers/pages_controller_spec.rb": 0.19468045234680176, + "spec/features/admin/feature_flags_spec.rb": 0.726452112197876, + "spec/models/signature_sheet_spec.rb": 0.6403882503509521, + "spec/features/admin/poll/officers_spec.rb": 1.2912020683288574, + "spec/models/lock_spec.rb": 0.08562397956848145, + "spec/helpers/proposals_helper_spec.rb": 0.17275524139404297, + "spec/features/tags/budget_investments_spec.rb": 14.154245615005493, + "spec/models/vote_spec.rb": 0.9258472919464111, + "spec/features/admin/site_customization/pages_spec.rb": 1.0365827083587646, + "spec/features/moderation/users_spec.rb": 1.3000907897949219, + "spec/features/comments/legislation_annotations_spec.rb": 19.67066717147827, + "spec/features/admin/legislation/questions_spec.rb": 4.043334007263184, + "spec/models/comment_spec.rb": 1.6633994579315186, + "spec/features/admin/site_customization/images_spec.rb": 1.2299704551696777, + "spec/models/abilities/valuator_spec.rb": 1.1985805034637451, + "spec/models/organization_spec.rb": 0.12121891975402832, + "spec/models/budget/ballot_spec.rb": 0.6403298377990723, + "spec/lib/wysiwyg_sanitizer_spec.rb": 0.0018651485443115234, + "spec/features/stats_spec.rb": 0.8169982433319092, + "spec/models/poll/answer_spec.rb": 0.13266730308532715, + "spec/features/admin/settings_spec.rb": 3.1228368282318115, + "spec/features/verification/verification_path_spec.rb": 1.1146795749664307, + "spec/controllers/management/users_controller_spec.rb": 0.004178762435913086, + "spec/models/direct_upload_spec.rb": 1.1311051845550537, + "spec/features/management/email_verifications_spec.rb": 0.3727388381958008, + "spec/models/abilities/administrator_spec.rb": 2.355985164642334, + "spec/models/budget/ballot/line_spec.rb": 0.49976515769958496, + "spec/features/verification/letter_spec.rb": 1.5464122295379639, + "spec/features/notifications_spec.rb": 19.54401397705078, + "spec/features/admin/administrators_spec.rb": 1.7901337146759033, + "spec/models/signature_spec.rb": 1.5397937297821045, + "spec/models/identity_spec.rb": 0.0023458003997802734, + "spec/models/verification/management/document_spec.rb": 0.017922163009643555, + "spec/models/legislation/process_spec.rb": 0.09648776054382324, + "spec/models/budget/group_spec.rb": 0.049637794494628906, + "spec/models/verification/management/email_spec.rb": 0.057023048400878906, + "spec/helpers/verification_helper_spec.rb": 0.0009088516235351562, + "spec/features/verification/residence_spec.rb": 2.2246382236480713, + "spec/features/tracks_spec.rb": 2.320988178253174, + "spec/lib/tag_sanitizer_spec.rb": 0.0005729198455810547, + "spec/features/admin/budgets_spec.rb": 4.4486541748046875, + "spec/models/site_customization/content_block_spec.rb": 0.010473012924194336, + "spec/features/verification/email_spec.rb": 0.5266687870025635, + "spec/models/budget/reclassified_vote_spec.rb": 0.19786882400512695, + "spec/features/management/proposals_spec.rb": 4.107697486877441, + "spec/models/poll/poll_spec.rb": 0.38217735290527344, + "spec/features/admin/geozones_spec.rb": 1.561723232269287, + "spec/lib/graphql_spec.rb": 3.063258647918701, + "spec/features/verification/verified_user_spec.rb": 0.8179008960723877 } \ No newline at end of file diff --git a/lib/census_api.rb b/lib/census_api.rb index 066c0be95..4fdbd37cb 100644 --- a/lib/census_api.rb +++ b/lib/census_api.rb @@ -84,7 +84,7 @@ class CensusApi end def stubbed_response(document_type, document_number) - if document_number == "12345678Z" && document_type == "1" + if (document_number == "12345678Z" || document_number == "12345678Y") && document_type == "1" stubbed_valid_response else stubbed_invalid_response @@ -119,7 +119,7 @@ class CensusApi {get_habita_datos_response: {get_habita_datos_return: {datos_habitante: {}, datos_vivienda: {}}}} end - def is_dni?(document_type) + def dni?(document_type) document_type.to_s == "1" end diff --git a/lib/document_parser.rb b/lib/document_parser.rb index c60b180dc..9e59c6b75 100644 --- a/lib/document_parser.rb +++ b/lib/document_parser.rb @@ -5,7 +5,7 @@ module DocumentParser document_number = document_number.to_s.gsub(/[^0-9A-Za-z]/i, '') variants = [] - if is_dni?(document_type) + if dni?(document_type) document_number, letter = split_letter_from(document_number) number_variants = get_number_variants_with_leading_zeroes_from(document_number) letter_variants = get_letter_variants(number_variants, letter) diff --git a/lib/local_census.rb b/lib/local_census.rb index 6c6e8fe12..1a0428787 100644 --- a/lib/local_census.rb +++ b/lib/local_census.rb @@ -63,7 +63,7 @@ class LocalCensus LocalCensusRecord.find_by(document_type: document_type, document_number: document_number) end - def is_dni?(document_type) + def dni?(document_type) document_type.to_s == "1" end diff --git a/spec/factories.rb b/spec/factories.rb index b90f68175..b98fc7adb 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -52,6 +52,12 @@ FactoryGirl.define do trait :verified do verified_at Time.current end + + trait :in_census do + document_number "12345678Z" + document_type "1" + verified_at Time.current + end end factory :identity do @@ -318,6 +324,21 @@ FactoryGirl.define do feasibility "feasible" valuation_finished true end + + end + + factory :image do + attachment { File.new("spec/fixtures/files/clippy.jpg") } + title "Lorem ipsum dolor sit amet" + association :user, factory: :user + + trait :proposal_image do + association :imageable, factory: :proposal + end + + trait :budget_investment_image do + association :imageable, factory: :budget_investment + end end factory :budget_ballot, class: 'Budget::Ballot' do @@ -468,6 +489,11 @@ FactoryGirl.define do ends_at { 15.days.ago } end + trait :recounting do + starts_at { 1.month.ago } + ends_at { Date.current } + end + trait :published do published true end @@ -477,8 +503,25 @@ FactoryGirl.define do poll association :author, factory: :user sequence(:title) { |n| "Question title #{n}" } - sequence(:description) { |n| "Question description #{n}" } - valid_answers { Faker::Lorem.words(3).join(', ') } + + trait :with_answers do + after(:create) do |question, _evaluator| + create(:poll_question_answer, question: question, title: "Yes") + create(:poll_question_answer, question: question, title: "No") + end + end + end + + factory :poll_question_answer, class: 'Poll::Question::Answer' do + association :question, factory: :poll_question + sequence(:title) { |n| "Answer title #{n}" } + sequence(:description) { |n| "Answer description #{n}" } + end + + factory :poll_answer_video, class: 'Poll::Question::Answer::Video' do + association :answer, factory: :poll_question_answer + title "Sample video title" + url "https://youtu.be/nhuNb0XtRhQ" end factory :poll_booth, class: 'Poll::Booth' do @@ -505,11 +548,21 @@ FactoryGirl.define do association :booth, factory: :poll_booth association :officer, factory: :poll_officer date Date.current + + trait :vote_collection_task do + task 0 + end + + trait :recount_scrutiny_task do + task 1 + end end factory :poll_voter, class: 'Poll::Voter' do poll association :user, :level_two + association :officer, factory: :poll_officer + origin "web" trait :from_booth do association :booth_assignment, factory: :poll_booth_assignment @@ -527,29 +580,19 @@ FactoryGirl.define do end factory :poll_answer, class: 'Poll::Answer' do - association :question, factory: :poll_question + association :question, factory: [:poll_question, :with_answers] association :author, factory: [:user, :level_two] - answer { question.valid_answers.sample } + answer { question.question_answers.sample.title } end factory :poll_partial_result, class: 'Poll::PartialResult' do - association :question, factory: :poll_question + association :question, factory: [:poll_question, :with_answers] association :author, factory: :user origin { 'web' } - answer { question.valid_answers.sample } + answer { question.question_answers.sample.title } end - factory :poll_white_result, class: 'Poll::WhiteResult' do - association :author, factory: :user - origin { 'web' } - end - - factory :poll_null_result, class: 'Poll::NullResult' do - association :author, factory: :user - origin { 'web' } - end - - factory :poll_total_result, class: 'Poll::TotalResult' do + factory :poll_recount, class: 'Poll::Recount' do association :author, factory: :user origin { 'web' } end @@ -804,4 +847,39 @@ LOREM_IPSUM association :author, factory: :user end + factory :direct_upload do + user + + trait :proposal do + resource_type "Proposal" + end + trait :budget_investment do + resource_type "Budget::Investment" + end + + trait :documents do + resource_relation "documents" + attachment { File.new("spec/fixtures/files/empty.pdf") } + end + trait :image do + resource_relation "image" + attachment { File.new("spec/fixtures/files/clippy.jpg") } + end + initialize_with { new(attributes) } + end + + factory :map_location do + latitude 51.48 + longitude 0.0 + zoom 10 + + trait :proposal_map_location do + proposal + end + + trait :budget_investment_map_location do + association :investment, factory: :budget_investment + end + end + end diff --git a/spec/features/admin/administrators_spec.rb b/spec/features/admin/administrators_spec.rb index bef57b75d..c39d5ade5 100644 --- a/spec/features/admin/administrators_spec.rb +++ b/spec/features/admin/administrators_spec.rb @@ -16,7 +16,7 @@ feature 'Admin administrators' do end scenario 'Create Administrator', :js do - fill_in 'email', with: @user.email + fill_in 'name_or_email', with: @user.email click_button 'Search' expect(page).to have_content @user.name @@ -41,5 +41,53 @@ feature 'Admin administrators' do expect(page).to have_content I18n.t("admin.administrators.administrator.restricted_removal") end end -end + context 'Search' do + + background do + user = create(:user, username: 'Bernard Sumner', email: 'bernard@sumner.com') + user2 = create(:user, username: 'Tony Soprano', email: 'tony@soprano.com') + @administrator1 = create(:administrator, user: user) + @administrator2 = create(:administrator, user: user2) + visit admin_administrators_path + end + + scenario 'returns no results if search term is empty' do + expect(page).to have_content(@administrator1.name) + expect(page).to have_content(@administrator2.name) + + fill_in 'name_or_email', with: ' ' + click_button 'Search' + + expect(page).to have_content('Administrators: User search') + expect(page).to have_content('No results found') + expect(page).to_not have_content(@administrator1.name) + expect(page).to_not have_content(@administrator2.name) + end + + scenario 'search by name' do + expect(page).to have_content(@administrator1.name) + expect(page).to have_content(@administrator2.name) + + fill_in 'name_or_email', with: 'Sumn' + click_button 'Search' + + expect(page).to have_content('Administrators: User search') + expect(page).to have_content(@administrator1.name) + expect(page).to_not have_content(@administrator2.name) + end + + scenario 'search by email' do + expect(page).to have_content(@administrator1.email) + expect(page).to have_content(@administrator2.email) + + fill_in 'name_or_email', with: @administrator2.email + click_button 'Search' + + expect(page).to have_content('Administrators: User search') + expect(page).to have_content(@administrator2.email) + expect(page).to_not have_content(@administrator1.email) + end + end + +end diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index 7252e2660..1ad89e6aa 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -421,20 +421,37 @@ feature 'Admin budget investments' do end end - scenario "Only displays valuation tags" do + scenario "Changes valuation and user generated tags" do budget_investment = create(:budget_investment, tag_list: 'Park') budget_investment.set_tag_list_on(:valuation, 'Education') budget_investment.save visit admin_budget_budget_investment_path(budget_investment.budget, budget_investment) - expect(page).to have_content "Education" - expect(page).to_not have_content "Park" + within("#user-tags") do + expect(page).to_not have_content "Education" + expect(page).to have_content "Park" + end click_link 'Edit classification' - expect(page).to have_content "Education" - expect(page).to_not have_content "Park" + fill_in 'budget_investment_tag_list', with: 'Park, Trees' + fill_in 'budget_investment_valuation_tag_list', with: 'Education, Environment' + click_button 'Update' + + visit admin_budget_budget_investment_path(budget_investment.budget, budget_investment) + + within("#user-tags") do + expect(page).to_not have_content "Education" + expect(page).to_not have_content "Environment" + expect(page).to have_content "Park, Trees" + end + + within("#tags") do + expect(page).to have_content "Education, Environment" + expect(page).to_not have_content "Park" + expect(page).to_not have_content "Trees" + end end scenario "Maintains user tags" do diff --git a/spec/features/admin/managers_spec.rb b/spec/features/admin/managers_spec.rb index 54b8cc77a..e59b1da4c 100644 --- a/spec/features/admin/managers_spec.rb +++ b/spec/features/admin/managers_spec.rb @@ -16,7 +16,7 @@ feature 'Admin managers' do end scenario 'Create Manager', :js do - fill_in 'email', with: @user.email + fill_in 'name_or_email', with: @user.email click_button 'Search' expect(page).to have_content @user.name @@ -34,4 +34,52 @@ feature 'Admin managers' do end end -end \ No newline at end of file + context 'Search' do + + background do + user = create(:user, username: 'Taylor Swift', email: 'taylor@swift.com') + user2 = create(:user, username: 'Stephanie Corneliussen', email: 'steph@mrrobot.com') + @manager1 = create(:manager, user: user) + @manager2 = create(:manager, user: user2) + visit admin_managers_path + end + + scenario 'returns no results if search term is empty' do + expect(page).to have_content(@manager1.name) + expect(page).to have_content(@manager2.name) + + fill_in 'name_or_email', with: ' ' + click_button 'Search' + + expect(page).to have_content('Managers: User search') + expect(page).to have_content('No results found') + expect(page).to_not have_content(@manager1.name) + expect(page).to_not have_content(@manager2.name) + end + + scenario 'search by name' do + expect(page).to have_content(@manager1.name) + expect(page).to have_content(@manager2.name) + + fill_in 'name_or_email', with: 'Taylor' + click_button 'Search' + + expect(page).to have_content('Managers: User search') + expect(page).to have_content(@manager1.name) + expect(page).to_not have_content(@manager2.name) + end + + scenario 'search by email' do + expect(page).to have_content(@manager1.email) + expect(page).to have_content(@manager2.email) + + fill_in 'name_or_email', with: @manager2.email + click_button 'Search' + + expect(page).to have_content('Managers: User search') + expect(page).to have_content(@manager2.email) + expect(page).to_not have_content(@manager1.email) + end + end + +end diff --git a/spec/features/admin/moderators_spec.rb b/spec/features/admin/moderators_spec.rb index e8e29b182..8a32762f1 100644 --- a/spec/features/admin/moderators_spec.rb +++ b/spec/features/admin/moderators_spec.rb @@ -16,7 +16,7 @@ feature 'Admin moderators' do end scenario 'Create Moderator', :js do - fill_in 'email', with: @user.email + fill_in 'name_or_email', with: @user.email click_button 'Search' expect(page).to have_content @user.name @@ -33,5 +33,53 @@ feature 'Admin moderators' do expect(page).to_not have_content @moderator.name end end -end + context 'Search' do + + background do + user = create(:user, username: 'Elizabeth Bathory', email: 'elizabeth@bathory.com') + user2 = create(:user, username: 'Ada Lovelace', email: 'ada@lovelace.com') + @moderator1 = create(:moderator, user: user) + @moderator2 = create(:moderator, user: user2) + visit admin_moderators_path + end + + scenario 'returns no results if search term is empty' do + expect(page).to have_content(@moderator1.name) + expect(page).to have_content(@moderator2.name) + + fill_in 'name_or_email', with: ' ' + click_button 'Search' + + expect(page).to have_content('Moderators: User search') + expect(page).to have_content('No results found') + expect(page).to_not have_content(@moderator1.name) + expect(page).to_not have_content(@moderator2.name) + end + + scenario 'search by name' do + expect(page).to have_content(@moderator1.name) + expect(page).to have_content(@moderator2.name) + + fill_in 'name_or_email', with: 'Eliz' + click_button 'Search' + + expect(page).to have_content('Moderators: User search') + expect(page).to have_content(@moderator1.name) + expect(page).to_not have_content(@moderator2.name) + end + + scenario 'search by email' do + expect(page).to have_content(@moderator1.email) + expect(page).to have_content(@moderator2.email) + + fill_in 'name_or_email', with: @moderator2.email + click_button 'Search' + + expect(page).to have_content('Moderators: User search') + expect(page).to have_content(@moderator2.email) + expect(page).to_not have_content(@moderator1.email) + end + end + +end diff --git a/spec/features/admin/organizations_spec.rb b/spec/features/admin/organizations_spec.rb index 814aa9df2..58375f569 100644 --- a/spec/features/admin/organizations_spec.rb +++ b/spec/features/admin/organizations_spec.rb @@ -95,7 +95,7 @@ feature 'Admin::Organizations' do click_on 'Verify' end expect(current_path).to eq(admin_organizations_path) - expect(page).to have_content ('Verified') + expect(page).to have_content 'Verified' expect(organization.reload.verified?).to eq(true) end @@ -108,18 +108,18 @@ feature 'Admin::Organizations' do click_on "Verified" within("#organization_#{organization.id}") do - expect(page).to have_content ('Verified') + expect(page).to have_content 'Verified' expect(page).to_not have_link('Verify') expect(page).to have_link('Reject') click_on 'Reject' end expect(current_path).to eq(admin_organizations_path) - expect(page).to_not have_content (organization.name) + expect(page).to_not have_content organization.name click_on 'Rejected' - expect(page).to have_content ('Rejected') - expect(page).to have_content (organization.name) + expect(page).to have_content 'Rejected' + expect(page).to have_content organization.name expect(organization.reload.rejected?).to eq(true) end @@ -137,10 +137,10 @@ feature 'Admin::Organizations' do click_on 'Verify' end expect(current_path).to eq(admin_organizations_path) - expect(page).to_not have_content (organization.name) + expect(page).to_not have_content organization.name click_on('Verified') - expect(page).to have_content (organization.name) + expect(page).to have_content organization.name expect(organization.reload.verified?).to eq(true) end diff --git a/spec/features/admin/poll/booth_assigments_spec.rb b/spec/features/admin/poll/booth_assigments_spec.rb index 09a21dd72..cceec1a3e 100644 --- a/spec/features/admin/poll/booth_assigments_spec.rb +++ b/spec/features/admin/poll/booth_assigments_spec.rb @@ -7,66 +7,109 @@ feature 'Admin booths assignments' do login_as(admin.user) end - scenario 'Assign booth to poll', :js do - poll = create(:poll) - booth = create(:poll_booth) + feature 'Admin Booth Assignment management' do - visit admin_poll_path(poll) - within('#poll-resources') do - click_link 'Booths (0)' + let!(:poll) { create(:poll) } + let!(:booth) { create(:poll_booth) } + + scenario 'List Polls and Booths to manage', :js do + second_poll = create(:poll) + second_booth = create(:poll_booth) + + visit booth_assignments_admin_polls_path + + expect(page).to have_content(poll.name) + expect(page).to have_content(second_poll.name) + + within("#poll_#{second_poll.id}") do + click_link 'Manage assignments' + end + + expect(page).to have_content "Assignments for poll '#{second_poll.name}'" + + expect(page).to have_content(booth.name) + expect(page).to have_content(second_booth.name) end - expect(page).to have_content 'There are no booths assigned to this poll.' + scenario 'Assign booth to poll', :js do + visit admin_poll_path(poll) + within('#poll-resources') do + click_link 'Booths (0)' + end - fill_in 'search-booths', with: booth.name - click_button 'Search' - expect(page).to have_content(booth.name) + expect(page).to have_content 'There are no booths assigned to this poll.' + expect(page).to_not have_content booth.name - within('#search-booths-results') do - click_link 'Assign booth' + fill_in 'search-booths', with: booth.name + click_button 'Search' + expect(page).to have_content(booth.name) + + visit manage_admin_poll_booth_assignments_path(poll) + + expect(page).to have_content "Assignments for poll '#{poll.name}'" + + within("#poll_booth_#{booth.id}") do + expect(page).to have_content(booth.name) + expect(page).to have_content "Unassigned" + + click_link 'Assign booth' + + expect(page).not_to have_content "Unassigned" + expect(page).to have_content "Assigned" + expect(page).to have_link "Unassign booth" + end + + visit admin_poll_path(poll) + within('#poll-resources') do + click_link 'Booths (1)' + end + + expect(page).to_not have_content 'There are no booths assigned to this poll.' + expect(page).to have_content booth.name end - expect(page).to have_content 'Booth assigned' + scenario 'Unassign booth from poll', :js do + assignment = create(:poll_booth_assignment, poll: poll, booth: booth) - visit admin_poll_path(poll) - within('#poll-resources') do - click_link 'Booths (1)' + visit admin_poll_path(poll) + within('#poll-resources') do + click_link 'Booths (1)' + end + + expect(page).not_to have_content 'There are no booths assigned to this poll.' + expect(page).to have_content booth.name + + fill_in 'search-booths', with: booth.name + click_button 'Search' + expect(page).to have_content(booth.name) + + visit manage_admin_poll_booth_assignments_path(poll) + + expect(page).to have_content "Assignments for poll '#{poll.name}'" + + within("#poll_booth_#{booth.id}") do + expect(page).to have_content(booth.name) + expect(page).to have_content "Assigned" + + click_link 'Unassign booth' + + expect(page).to have_content "Unassigned" + expect(page).not_to have_content "Assigned" + expect(page).to have_link "Assign booth" + end + + visit admin_poll_path(poll) + within('#poll-resources') do + click_link 'Booths (0)' + end + + expect(page).to have_content 'There are no booths assigned to this poll.' + expect(page).not_to have_content booth.name end - - expect(page).to_not have_content 'There are no booths assigned to this poll.' - expect(page).to have_content booth.name - end - - scenario 'Remove booth from poll', :js do - poll = create(:poll) - booth = create(:poll_booth) - assignment = create(:poll_booth_assignment, poll: poll, booth: booth) - - visit admin_poll_path(poll) - within('#poll-resources') do - click_link 'Booths (1)' - end - - expect(page).to_not have_content 'There are no booths assigned to this poll.' - expect(page).to have_content booth.name - - within("#poll_booth_assignment_#{assignment.id}") do - click_link 'Remove booth from poll' - end - - expect(page).to have_content 'Booth not assigned anymore' - - visit admin_poll_path(poll) - within('#poll-resources') do - click_link 'Booths (0)' - end - - expect(page).to have_content 'There are no booths assigned to this poll.' - expect(page).to_not have_content booth.name end feature 'Show' do - scenario 'Lists all assigned poll oficers' do + scenario 'Lists all assigned poll officers' do poll = create(:poll) booth = create(:poll_booth) booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) @@ -97,11 +140,8 @@ feature 'Admin booths assignments' do officer_assignment_2 = create(:poll_officer_assignment, booth_assignment: booth_assignment, date: poll.ends_at) final_officer_assignment = create(:poll_officer_assignment, :final, booth_assignment: booth_assignment, date: poll.ends_at) - total_recount = create(:poll_total_result, - booth_assignment: booth_assignment, - officer_assignment: final_officer_assignment, - date: final_officer_assignment.date, - amount: 5678) + create(:poll_voter, poll: poll, booth_assignment: booth_assignment, created_at: poll.starts_at.to_date) + create(:poll_voter, poll: poll, booth_assignment: booth_assignment, created_at: poll.ends_at.to_date) booth_assignment_2 = create(:poll_booth_assignment, poll: poll) @@ -111,12 +151,122 @@ feature 'Admin booths assignments' do within('#assigned_booths_list') { click_link booth.name } click_link 'Recounts' + + within('#totals') do + within("#total_system") { expect(page).to have_content "2" } + end + within('#recounts_list') do - within("#recounting_#{total_recount.date.strftime('%Y%m%d')}") do - expect(page).to have_content total_recount.amount + within("#recounting_#{poll.starts_at.to_date.strftime('%Y%m%d')}") do + expect(page).to have_content 1 + end + within("#recounting_#{(poll.ends_at.to_date - 5.days).strftime('%Y%m%d')}") do + expect(page).to have_content '-' + end + within("#recounting_#{poll.ends_at.to_date.strftime('%Y%m%d')}") do + expect(page).to have_content 1 end end end + scenario 'Results for a booth assignment' do + poll = create(:poll) + booth_assignment = create(:poll_booth_assignment, poll: poll) + other_booth_assignment = create(:poll_booth_assignment, poll: poll) + + question_1 = create(:poll_question, poll: poll) + create(:poll_question_answer, title: 'Yes', question: question_1) + create(:poll_question_answer, title: 'No', question: question_1) + + question_2 = create(:poll_question, poll: poll) + create(:poll_question_answer, title: 'Today', question: question_2) + create(:poll_question_answer, title: 'Tomorrow', question: question_2) + + create(:poll_partial_result, + booth_assignment: booth_assignment, + question: question_1, + answer: 'Yes', + amount: 11) + + create(:poll_partial_result, + booth_assignment: booth_assignment, + question: question_1, + answer: 'No', + amount: 4) + + create(:poll_partial_result, + booth_assignment: booth_assignment, + question: question_2, + answer: 'Today', + amount: 5) + + create(:poll_partial_result, + booth_assignment: booth_assignment, + question: question_2, + answer: 'Tomorrow', + amount: 6) + + create(:poll_partial_result, + booth_assignment: other_booth_assignment, + question: question_1, + answer: 'Yes', + amount: 9999) + + create(:poll_recount, + booth_assignment: booth_assignment, + white_amount: 21, + null_amount: 44, + total_amount: 66) + + create(:poll_recount, + booth_assignment: other_booth_assignment, + white_amount: 999, + null_amount: 999, + total_amount: 999) + + visit admin_poll_booth_assignment_path(poll, booth_assignment) + + click_link 'Results' + + expect(page).to have_content(question_1.title) + + within("#question_#{question_1.id}_0_result") do + expect(page).to have_content("Yes") + expect(page).to have_content(11) + end + + within("#question_#{question_1.id}_1_result") do + expect(page).to have_content("No") + expect(page).to have_content(4) + end + + expect(page).to have_content(question_2.title) + + within("#question_#{question_2.id}_0_result") do + expect(page).to have_content("Today") + expect(page).to have_content(5) + end + + within("#question_#{question_2.id}_1_result") do + expect(page).to have_content("Tomorrow") + expect(page).to have_content(6) + end + + within('#white_results') { expect(page).to have_content('21') } + within('#null_results') { expect(page).to have_content('44') } + within('#total_results') { expect(page).to have_content('66') } + end + + scenario "No results" do + poll = create(:poll) + booth_assignment = create(:poll_booth_assignment, poll: poll) + + visit admin_poll_booth_assignment_path(poll, booth_assignment) + + click_link "Results" + + expect(page).to have_content "There are no results" + end + end end diff --git a/spec/features/admin/poll/booths_spec.rb b/spec/features/admin/poll/booths_spec.rb index 13f3af2ff..1aa487b26 100644 --- a/spec/features/admin/poll/booths_spec.rb +++ b/spec/features/admin/poll/booths_spec.rb @@ -60,6 +60,7 @@ feature 'Admin booths' do expect(page).to have_content booth_for_current_poll.name expect(page).to have_content booth_for_incoming_poll.name expect(page).to_not have_content booth_for_expired_poll.name + expect(page).to_not have_link "Edit booth" end scenario 'Show' do @@ -87,12 +88,15 @@ feature 'Admin booths' do end scenario "Edit" do + poll = create(:poll, :current) booth = create(:poll_booth) + assignment = create(:poll_booth_assignment, poll: poll, booth: booth) visit admin_booths_path within("#booth_#{booth.id}") do - click_link "Edit" + expect(page).to_not have_link "Manage shifts" + click_link "Edit booth" end fill_in "poll_booth_name", with: "Next booth" @@ -109,4 +113,18 @@ feature 'Admin booths' do end end -end \ No newline at end of file + scenario "Back link go back to available list when manage shifts" do + poll = create(:poll, :current) + booth = create(:poll_booth) + assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + + visit available_admin_booths_path + + within("#booth_#{booth.id}") do + click_link "Manage shifts" + end + + click_link "Go back" + expect(current_path).to eq(available_admin_booths_path) + end +end diff --git a/spec/features/admin/poll/officer_assignments_spec.rb b/spec/features/admin/poll/officer_assignments_spec.rb new file mode 100644 index 000000000..48d10ad39 --- /dev/null +++ b/spec/features/admin/poll/officer_assignments_spec.rb @@ -0,0 +1,67 @@ +require 'rails_helper' + +feature 'Officer Assignments' do + + background do + admin = create(:administrator) + login_as(admin.user) + end + + scenario "Index" do + poll = create(:poll) + booth = create(:poll_booth) + + officer1 = create(:poll_officer) + officer2 = create(:poll_officer) + officer3 = create(:poll_officer) + + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + officer_assignment = create(:poll_officer_assignment, booth_assignment: booth_assignment, officer: officer1) + + booth_assignment_2 = create(:poll_booth_assignment, poll: poll) + officer_assignment_2 = create(:poll_officer_assignment, booth_assignment: booth_assignment_2, officer: officer2) + + visit admin_poll_path(poll) + + click_link 'Officers (2)' + + within('#officer_assignments') do + expect(page).to have_content officer1.name + expect(page).to have_content officer2.name + expect(page).to_not have_content officer3.name + end + end + + scenario "Search", :js do + poll = create(:poll) + booth = create(:poll_booth) + + user1 = create(:user, username: "John Snow") + user2 = create(:user, username: "John Silver") + user3 = create(:user, username: "John Edwards") + + officer1 = create(:poll_officer, user: user1) + officer2 = create(:poll_officer, user: user2) + officer3 = create(:poll_officer, user: user3) + + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + officer_assignment = create(:poll_officer_assignment, booth_assignment: booth_assignment, officer: officer1) + + booth_assignment_2 = create(:poll_booth_assignment, poll: poll) + officer_assignment_2 = create(:poll_officer_assignment, booth_assignment: booth_assignment_2, officer: officer2) + + visit admin_poll_path(poll) + + click_link 'Officers (2)' + + fill_in "search-officers", with: "John" + click_button "Search" + + within('#search-officers-results') do + expect(page).to have_content officer1.name + expect(page).to have_content officer2.name + expect(page).to_not have_content officer3.name + end + end + +end \ No newline at end of file diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb index 6eb64f6e1..210b2ff6a 100644 --- a/spec/features/admin/poll/polls_spec.rb +++ b/spec/features/admin/poll/polls_spec.rb @@ -58,6 +58,12 @@ feature 'Admin polls' do fill_in "poll_name", with: "Upcoming poll" fill_in 'poll_starts_at', with: start_date.strftime("%d/%m/%Y") fill_in 'poll_ends_at', with: end_date.strftime("%d/%m/%Y") + fill_in 'poll_summary', with: "Upcoming poll's summary. This poll..." + fill_in 'poll_description', with: "Upcomming poll's description. This poll..." + + expect(page).to_not have_css("#poll_results_enabled") + expect(page).to_not have_css("#poll_stats_enabled") + click_button "Create poll" expect(page).to have_content "Poll created successfully" @@ -68,19 +74,34 @@ feature 'Admin polls' do scenario "Edit" do poll = create(:poll) + create(:image, imageable: poll) visit admin_poll_path(poll) - click_link "Edit" + click_link "Edit poll" end_date = 1.year.from_now + expect(page).to have_css("img[alt='#{poll.image.title}']") + + expect(page).to have_css("#poll_results_enabled") + expect(page).to have_css("#poll_stats_enabled") + fill_in "poll_name", with: "Next Poll" fill_in 'poll_ends_at', with: end_date.strftime("%d/%m/%Y") + check 'poll_results_enabled' + check 'poll_stats_enabled' + click_button "Update poll" expect(page).to have_content "Poll updated successfully" expect(page).to have_content "Next Poll" expect(page).to have_content I18n.l(end_date.to_date) + + click_link "Edit poll" + + expect(page).to have_field('poll_results_enabled', checked: true) + expect(page).to have_field('poll_stats_enabled', checked: true) + end scenario 'Edit from index' do @@ -181,54 +202,6 @@ feature 'Admin polls' do expect(page).to_not have_content "There are no questions assigned to this poll" end - scenario 'Add question to poll', :js do - poll = create(:poll) - question = create(:poll_question, title: 'Should we rebuild the city?') - - visit admin_poll_path(poll) - - expect(page).to have_content 'Questions (0)' - expect(page).to have_content 'There are no questions assigned to this poll' - - fill_in 'search-questions', with: 'rebuild' - click_button 'Search' - - within('#search-questions-results') do - click_link 'Include question' - end - - expect(page).to have_content 'Question added to this poll' - - visit admin_poll_path(poll) - - expect(page).to have_content 'Questions (1)' - expect(page).to_not have_content 'There are no questions assigned to this poll' - expect(page).to have_content question.title - end - - scenario 'Remove question from poll', :js do - poll = create(:poll) - question = create(:poll_question, poll: poll) - - visit admin_poll_path(poll) - - expect(page).to have_content 'Questions (1)' - expect(page).to_not have_content 'There are no questions assigned to this poll' - expect(page).to have_content question.title - - within("#poll_question_#{question.id}") do - click_link 'Remove question from poll' - end - - expect(page).to have_content 'Question removed from this poll' - - visit admin_poll_path(poll) - - expect(page).to have_content 'Questions (0)' - expect(page).to have_content 'There are no questions assigned to this poll' - expect(page).to_not have_content question.title - end - end end @@ -249,18 +222,18 @@ feature 'Admin polls' do booth_assignment_final_recounted = create(:poll_booth_assignment, poll: poll) 3.times do |i| - create(:poll_total_result, + create(:poll_recount, booth_assignment: booth_assignment, date: poll.starts_at + i.days, - amount: 21) + total_amount: 21) end 2.times { create(:poll_voter, booth_assignment: booth_assignment_final_recounted) } - create(:poll_total_result, + create(:poll_recount, booth_assignment: booth_assignment_final_recounted, date: poll.ends_at, - amount: 55555) + total_amount: 55555) visit admin_poll_path(poll) @@ -303,8 +276,13 @@ feature 'Admin polls' do booth_assignment_2 = create(:poll_booth_assignment, poll: poll) booth_assignment_3 = create(:poll_booth_assignment, poll: poll) - question_1 = create(:poll_question, poll: poll, valid_answers: "Yes,No") - question_2 = create(:poll_question, poll: poll, valid_answers: "Today,Tomorrow") + question_1 = create(:poll_question, poll: poll) + create(:poll_question_answer, title: 'Yes', question: question_1) + create(:poll_question_answer, title: 'No', question: question_1) + + question_2 = create(:poll_question, poll: poll) + create(:poll_question_answer, title: 'Today', question: question_2) + create(:poll_question_answer, title: 'Tomorrow', question: question_2) [booth_assignment_1, booth_assignment_2, booth_assignment_3].each do |ba| create(:poll_partial_result, @@ -318,35 +296,72 @@ feature 'Admin polls' do answer: 'Tomorrow', amount: 5) end - create(:poll_white_result, + create(:poll_recount, booth_assignment: booth_assignment_1, - amount: 21) - create(:poll_null_result, - booth_assignment: booth_assignment_3, - amount: 44) + white_amount: 21, + null_amount: 44, + total_amount: 66) visit admin_poll_path(poll) click_link "Results" expect(page).to have_content(question_1.title) - question_1.valid_answers.each_with_index do |answer, i| + question_1.question_answers.each_with_index do |answer, i| within("#question_#{question_1.id}_#{i}_result") do - expect(page).to have_content(answer) + expect(page).to have_content(answer.title) expect(page).to have_content([33, 0][i]) end end expect(page).to have_content(question_2.title) - question_2.valid_answers.each_with_index do |answer, i| + question_2.question_answers.each_with_index do |answer, i| within("#question_#{question_2.id}_#{i}_result") do - expect(page).to have_content(answer) + expect(page).to have_content(answer.title) expect(page).to have_content([0, 15][i]) end end within('#white_results') { expect(page).to have_content('21') } within('#null_results') { expect(page).to have_content('44') } + within('#total_results') { expect(page).to have_content('66') } + end + + scenario "Link to results by booth" do + poll = create(:poll) + booth_assignment1 = create(:poll_booth_assignment, poll: poll) + booth_assignment2 = create(:poll_booth_assignment, poll: poll) + + question = create(:poll_question, poll: poll) + create(:poll_question_answer, title: 'Yes', question: question) + create(:poll_question_answer, title: 'No', question: question) + + create(:poll_partial_result, + booth_assignment: booth_assignment1, + question: question, + answer: 'Yes', + amount: 5) + + create(:poll_partial_result, + booth_assignment: booth_assignment2, + question: question, + answer: 'Yes', + amount: 6) + + visit admin_poll_path(poll) + + click_link "Results" + + expect(page).to have_link("See results", count: 2) + + within("#booth_assignment_#{booth_assignment1.id}_result") do + click_link "See results" + end + + expect(page).to have_content booth_assignment1.booth.name + expect(page).to have_content "Results" + expect(page).to have_content "Yes" + expect(page).to have_content "5" end end end diff --git a/spec/features/admin/poll/questions/answers/answers_spec.rb b/spec/features/admin/poll/questions/answers/answers_spec.rb new file mode 100644 index 000000000..e8af5ff79 --- /dev/null +++ b/spec/features/admin/poll/questions/answers/answers_spec.rb @@ -0,0 +1,71 @@ +require 'rails_helper' + +feature 'Answers' do + + background do + admin = create(:administrator) + login_as admin.user + end + + scenario 'Create' do + question = create(:poll_question) + title = 'Whatever the question may be, the answer is always 42' + description = "The Hitchhiker's Guide To The Universe" + + visit admin_question_path(question) + click_link 'Add answer' + + fill_in 'poll_question_answer_title', with: title + fill_in 'poll_question_answer_description', with: description + + click_button 'Save' + + expect(page).to have_content(title) + expect(page).to have_content(description) + end + + scenario 'Create second answer and place after the first one' do + question = create(:poll_question) + answer = create(:poll_question_answer, title: 'First', question: question, given_order: 1) + title = 'Second' + description = "Description" + + visit admin_question_path(question) + click_link 'Add answer' + + fill_in 'poll_question_answer_title', with: title + fill_in 'poll_question_answer_description', with: description + + click_button 'Save' + + expect(page.body.index('First')).to be < page.body.index('Second') + end + + scenario 'Update' do + question = create(:poll_question) + answer = create(:poll_question_answer, question: question, title: "Answer title", given_order: 2) + answer2 = create(:poll_question_answer, question: question, title: "Another title", given_order: 1) + + visit admin_answer_path(answer) + + click_link 'Edit answer' + + old_title = answer.title + new_title = 'Ex Machina' + + fill_in 'poll_question_answer_title', with: new_title + + click_button 'Save' + + expect(page).to have_content('Changes saved') + expect(page).to have_content(new_title) + + visit admin_question_path(question) + + expect(page).to have_content(new_title) + expect(page).to_not have_content(old_title) + + expect(page.body.index(new_title)).to be < page.body.index(answer2.title) + end + +end diff --git a/spec/features/admin/poll/questions/answers/images/images_spec.rb b/spec/features/admin/poll/questions/answers/images/images_spec.rb new file mode 100644 index 000000000..915c8d6b0 --- /dev/null +++ b/spec/features/admin/poll/questions/answers/images/images_spec.rb @@ -0,0 +1,14 @@ +require 'rails_helper' + +feature 'Images' do + + background do + admin = create(:administrator) + login_as(admin.user) + end + + pending "Index" + pending "Create" + pending "Destroy" + +end \ No newline at end of file diff --git a/spec/features/admin/poll/questions/answers/videos/videos_spec.rb b/spec/features/admin/poll/questions/answers/videos/videos_spec.rb new file mode 100644 index 000000000..35d07f454 --- /dev/null +++ b/spec/features/admin/poll/questions/answers/videos/videos_spec.rb @@ -0,0 +1,33 @@ +require 'rails_helper' + +feature 'Videos' do + + background do + admin = create(:administrator) + login_as(admin.user) + end + + scenario "Create" do + question = create(:poll_question) + answer = create(:poll_question_answer, question: question) + video_title = "'Magical' by Junko Ohashi" + video_url = "https://www.youtube.com/watch?v=-JMf43st-1A" + + visit admin_question_path(question) + + within("#poll_question_answer_#{answer.id}") do + click_link "Video list" + end + + click_link "Add video" + + fill_in 'poll_question_answer_video_title', with: video_title + fill_in 'poll_question_answer_video_url', with: video_url + + click_button "Save" + + expect(page).to have_content(video_title) + expect(page).to have_content(video_url) + end + +end diff --git a/spec/features/admin/poll/questions_spec.rb b/spec/features/admin/poll/questions_spec.rb index 392b2aabf..5c8cba9c1 100644 --- a/spec/features/admin/poll/questions_spec.rb +++ b/spec/features/admin/poll/questions_spec.rb @@ -24,9 +24,7 @@ feature 'Admin poll questions' do visit admin_question_path(question) expect(page).to have_content(question.title) - expect(page).to have_content(question.description) expect(page).to have_content(question.author.name) - expect(page).to have_content(question.valid_answers.join(" ")) end scenario 'Create' do @@ -45,13 +43,11 @@ feature 'Admin poll questions' do select 'Movies', from: 'poll_question_poll_id' fill_in 'poll_question_title', with: title - fill_in 'poll_question_description', with: description fill_in 'poll_question_video_url', with: video_url click_button 'Save' expect(page).to have_content(title) - expect(page).to have_content(description) expect(page).to have_content(video_url) end @@ -64,15 +60,12 @@ feature 'Admin poll questions' do expect(current_path).to eq(new_admin_question_path) expect(page).to have_field('poll_question_title', with: proposal.title) - expect(page).to have_field('poll_question_description', with: proposal.description) - expect(page).to have_field('poll_question_valid_answers', with: "Yes, No") select 'Proposals', from: 'poll_question_poll_id' click_button 'Save' expect(page).to have_content(proposal.title) - expect(page).to have_content(proposal.description) expect(page).to have_link(proposal.title, href: proposal_path(proposal)) expect(page).to have_link(proposal.author.name, href: user_path(proposal.author)) end diff --git a/spec/features/admin/poll/shifts_spec.rb b/spec/features/admin/poll/shifts_spec.rb index 1e5bb6328..bddd1b6b1 100644 --- a/spec/features/admin/poll/shifts_spec.rb +++ b/spec/features/admin/poll/shifts_spec.rb @@ -30,12 +30,18 @@ feature 'Admin shifts' do expect(page).to have_content officer.name end - scenario "Create", :js do - poll = create(:poll) + scenario "Create Vote Collection Shift and Recount & Scrutiny Shift on same date", :js do + create(:poll) + create(:poll, :incoming) + poll = create(:poll, :current) booth = create(:poll_booth) + create(:poll_booth_assignment, poll: poll, booth: booth) + create(:poll_booth_assignment, poll: create(:poll, :expired), booth: booth) officer = create(:poll_officer) + vote_collection_dates = (Date.current..poll.ends_at.to_date).to_a.map { |date| I18n.l(date, format: :long) } + recount_scrutiny_dates = (poll.ends_at.to_date..poll.ends_at.to_date + 1.week).to_a.map { |date| I18n.l(date, format: :long) } - visit admin_booths_path + visit available_admin_booths_path within("#booth_#{booth.id}") do click_link "Manage shifts" @@ -45,24 +51,85 @@ feature 'Admin shifts' do click_button "Search" click_link "Edit shifts" - select I18n.l(poll.starts_at.to_date, format: :long), from: 'shift_date' + expect(page).to have_select('shift_date_vote_collection_date', options: ["Select day", *vote_collection_dates]) + expect(page).not_to have_select('shift_date_recount_scrutiny_date') + select I18n.l(Date.current, format: :long), from: 'shift_date_vote_collection_date' click_button "Add shift" expect(page).to have_content "Shift added" within("#shifts") do expect(page).to have_css(".shift", count: 1) - expect(page).to have_content(I18n.l(poll.starts_at.to_date, format: :long)) + expect(page).to have_content(I18n.l(Date.current, format: :long)) + expect(page).to have_content("Collect Votes") + expect(page).to have_content(officer.name) + end + + visit available_admin_booths_path + + within("#booth_#{booth.id}") do + click_link "Manage shifts" + end + + fill_in "search", with: officer.email + click_button "Search" + click_link "Edit shifts" + + select "Recount & Scrutiny", from: 'shift_task' + + expect(page).to have_select('shift_date_recount_scrutiny_date', options: ["Select day", *recount_scrutiny_dates]) + expect(page).not_to have_select('shift_date_vote_collection_date') + select I18n.l(poll.ends_at.to_date + 4.days, format: :long), from: 'shift_date_recount_scrutiny_date' + click_button "Add shift" + + expect(page).to have_content "Shift added" + + within("#shifts") do + expect(page).to have_css(".shift", count: 2) + expect(page).to have_content(I18n.l(poll.ends_at.to_date + 4.days, format: :long)) + expect(page).to have_content("Recount & Scrutiny") expect(page).to have_content(officer.name) end end - scenario "Erros on create", :js do - poll = create(:poll) + scenario "Vote Collection Shift and Recount & Scrutiny Shift don't include already assigned dates to officer", :js do + poll = create(:poll, :current) booth = create(:poll_booth) + assignment = create(:poll_booth_assignment, poll: poll, booth: booth) officer = create(:poll_officer) - visit admin_booths_path + shift1 = create(:poll_shift, :vote_collection_task, officer: officer, booth: booth, date: Time.zone.today) + shift2 = create(:poll_shift, :recount_scrutiny_task, officer: officer, booth: booth, date: Time.zone.tomorrow) + + vote_collection_dates = (Date.current..poll.ends_at.to_date).to_a + .reject { |date| date == Time.zone.today } + .map { |date| I18n.l(date, format: :long) } + recount_scrutiny_dates = (poll.ends_at.to_date..poll.ends_at.to_date + 1.week).to_a + .reject { |date| date == Time.zone.tomorrow } + .map { |date| I18n.l(date, format: :long) } + + visit available_admin_booths_path + + within("#booth_#{booth.id}") do + click_link "Manage shifts" + end + + fill_in "search", with: officer.email + click_button "Search" + click_link "Edit shifts" + + expect(page).to have_select('shift_date_vote_collection_date', options: ["Select day", *vote_collection_dates]) + select "Recount & Scrutiny", from: 'shift_task' + expect(page).to have_select('shift_date_recount_scrutiny_date', options: ["Select day", *recount_scrutiny_dates]) + end + + scenario "Error on create", :js do + poll = create(:poll, :current) + booth = create(:poll_booth) + assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + officer = create(:poll_officer) + + visit available_admin_booths_path within("#booth_#{booth.id}") do click_link "Manage shifts" @@ -73,17 +140,18 @@ feature 'Admin shifts' do click_link "Edit shifts" click_button "Add shift" - expect(page).to have_content "can't be blank" + expect(page).to have_content "A date must be selected" end scenario "Destroy" do - poll = create(:poll) + poll = create(:poll, :current) booth = create(:poll_booth) + assignment = create(:poll_booth_assignment, poll: poll, booth: booth) officer = create(:poll_officer) shift = create(:poll_shift, officer: officer, booth: booth) - visit admin_booths_path + visit available_admin_booths_path within("#booth_#{booth.id}") do click_link "Manage shifts" diff --git a/spec/features/admin/settings_spec.rb b/spec/features/admin/settings_spec.rb index c92b4b525..40baf6423 100644 --- a/spec/features/admin/settings_spec.rb +++ b/spec/features/admin/settings_spec.rb @@ -28,4 +28,65 @@ feature 'Admin settings' do expect(page).to have_content 'Value updated' end -end \ No newline at end of file + describe "Update map" do + + scenario "Should not be able when map feature deactivated" do + Setting['feature.map'] = false + admin = create(:administrator).user + login_as(admin) + visit admin_settings_path + + expect(page).not_to have_content "Map configuration" + end + + scenario "Should be able when map feature activated" do + Setting['feature.map'] = true + admin = create(:administrator).user + login_as(admin) + visit admin_settings_path + + expect(page).to have_content "Map configuration" + end + + scenario "Should show successful notice" do + Setting['feature.map'] = true + admin = create(:administrator).user + login_as(admin) + visit admin_settings_path + + within "#map-form" do + click_on "Update" + end + + expect(page).to have_content "Map configuration updated succesfully" + end + + scenario "Should display marker by default", :js do + Setting['feature.map'] = true + admin = create(:administrator).user + login_as(admin) + + visit admin_settings_path + + expect(find("#latitude", visible: false).value).to eq "51.48" + expect(find("#longitude", visible: false).value).to eq "0.0" + end + + scenario "Should update marker", :js do + Setting['feature.map'] = true + admin = create(:administrator).user + login_as(admin) + + visit admin_settings_path + find("#admin-map").click + within "#map-form" do + click_on "Update" + end + + expect(find("#latitude", visible: false).value).not_to eq "51.48" + expect(page).to have_content "Map configuration updated succesfully" + end + + end + +end diff --git a/spec/features/admin/site_customization/images_spec.rb b/spec/features/admin/site_customization/images_spec.rb index 6d180fe8e..fc81bf246 100644 --- a/spec/features/admin/site_customization/images_spec.rb +++ b/spec/features/admin/site_customization/images_spec.rb @@ -20,7 +20,7 @@ feature "Admin custom images" do end expect(page).to have_css("tr.logo_header img[src*='logo_header.png']") - expect(page).to have_css("img[src*='logo_header.png']", count: 2) # one in the admin form an one in the page header + expect(page).to have_css("img[src*='logo_header.png']", count: 1) end scenario "Upload invalid image" do diff --git a/spec/features/admin/tags_spec.rb b/spec/features/admin/tags_spec.rb index dd9c38c6b..8ff205852 100644 --- a/spec/features/admin/tags_spec.rb +++ b/spec/features/admin/tags_spec.rb @@ -23,7 +23,7 @@ feature 'Admin tags' do within("form.new_tag") do fill_in "tag_name", with: 'important issues' - click_button 'Create Topic' + click_button 'Create topic' end visit admin_tags_path @@ -39,8 +39,8 @@ feature 'Admin tags' do expect(page).to have_content @tag1.name expect(page).to have_content tag2.name - within("#edit_tag_#{tag2.id}") do - click_link 'Destroy Topic' + within("#tag_#{tag2.id}") do + click_link 'Destroy topic' end visit admin_tags_path @@ -58,8 +58,8 @@ feature 'Admin tags' do expect(page).to have_content @tag1.name expect(page).to have_content tag2.name - within("#edit_tag_#{tag2.id}") do - click_link 'Destroy Topic' + within("#tag_#{tag2.id}") do + click_link 'Destroy topic' end visit admin_tags_path @@ -81,7 +81,7 @@ feature 'Admin tags' do within("form.new_tag") do fill_in "tag_name", with: "wow_category" - click_button 'Create Topic' + click_button 'Create topic' end expect(ActsAsTaggableOn::Tag.category.where(name: "wow_category")).to exist diff --git a/spec/features/admin/valuators_spec.rb b/spec/features/admin/valuators_spec.rb index d95432474..f1dfa68b3 100644 --- a/spec/features/admin/valuators_spec.rb +++ b/spec/features/admin/valuators_spec.rb @@ -2,32 +2,87 @@ require 'rails_helper' feature 'Admin valuators' do background do - @admin = create(:administrator) - @user = create(:user, username: 'Jose Luis Balbin') + @admin = create(:administrator) + @user = create(:user, username: 'Jose Luis Balbin') @valuator = create(:valuator) login_as(@admin.user) visit admin_valuators_path end scenario 'Index' do - expect(page).to have_content @valuator.name - expect(page).to have_content @valuator.email - expect(page).to_not have_content @user.name + expect(page).to have_content(@valuator.name) + expect(page).to have_content(@valuator.email) + expect(page).to_not have_content(@user.name) end scenario 'Create Valuator', :js do - fill_in 'email', with: @user.email + fill_in 'name_or_email', with: @user.email click_button 'Search' - expect(page).to have_content @user.name + expect(page).to have_content(@user.name) fill_in 'valuator_description', with: 'environmental expert' click_button 'Add to valuators' - within("#valuators") do - expect(page).to have_content @user.name - expect(page).to have_content 'environmental expert' + within('#valuators') do + expect(page).to have_content(@user.name) + expect(page).to have_content('environmental expert') + end + end + + scenario 'Delete Valuator' do + click_link 'Delete' + + within('#valuators') do + expect(page).to_not have_content(@valuator.name) + end + end + + context 'Search' do + + background do + user = create(:user, username: 'David Foster Wallace', email: 'david@wallace.com') + user2 = create(:user, username: 'Steven Erikson', email: 'steven@erikson.com') + @valuator1 = create(:valuator, user: user) + @valuator2 = create(:valuator, user: user2) + visit admin_valuators_path + end + + scenario 'returns no results if search term is empty' do + expect(page).to have_content(@valuator1.name) + expect(page).to have_content(@valuator2.name) + + fill_in 'name_or_email', with: ' ' + click_button 'Search' + + expect(page).to have_content('Valuators: User search') + expect(page).to have_content('No results found') + expect(page).to_not have_content(@valuator1.name) + expect(page).to_not have_content(@valuator2.name) + end + + scenario 'search by name' do + expect(page).to have_content(@valuator1.name) + expect(page).to have_content(@valuator2.name) + + fill_in 'name_or_email', with: 'Foster' + click_button 'Search' + + expect(page).to have_content('Valuators: User search') + expect(page).to have_content(@valuator1.name) + expect(page).to_not have_content(@valuator2.name) + end + + scenario 'search by email' do + expect(page).to have_content(@valuator1.email) + expect(page).to have_content(@valuator2.email) + + fill_in 'name_or_email', with: @valuator2.email + click_button 'Search' + + expect(page).to have_content('Valuators: User search') + expect(page).to have_content(@valuator2.email) + expect(page).to_not have_content(@valuator1.email) end end end - diff --git a/spec/features/admin_spec.rb b/spec/features/admin_spec.rb index 9ea2c2390..f2374f183 100644 --- a/spec/features/admin_spec.rb +++ b/spec/features/admin_spec.rb @@ -12,7 +12,7 @@ feature 'Admin' do visit admin_root_path expect(current_path).not_to eq(admin_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -22,7 +22,7 @@ feature 'Admin' do visit admin_root_path expect(current_path).not_to eq(admin_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -32,7 +32,7 @@ feature 'Admin' do visit admin_root_path expect(current_path).not_to eq(admin_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -42,7 +42,7 @@ feature 'Admin' do visit admin_root_path expect(current_path).not_to eq(admin_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -52,7 +52,7 @@ feature 'Admin' do visit admin_root_path expect(current_path).not_to eq(admin_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end diff --git a/spec/features/budgets/investments_spec.rb b/spec/features/budgets/investments_spec.rb index 820ebb520..d17bd9c91 100644 --- a/spec/features/budgets/investments_spec.rb +++ b/spec/features/budgets/investments_spec.rb @@ -28,6 +28,21 @@ feature 'Budget Investments' do end end + scenario 'Index should show investment descriptive image only when is defined' do + investment = create(:budget_investment, heading: heading) + investment_with_image = create(:budget_investment, heading: heading) + image = create(:image, imageable: investment_with_image) + + visit budget_investments_path(budget, heading_id: heading.id) + + within("#budget_investment_#{investment.id}") do + expect(page).to have_css("div.no-image") + end + within("#budget_investment_#{investment_with_image.id}") do + expect(page).to have_css("img[alt='#{investment_with_image.image.title}']") + end + end + context("Search") do scenario 'Search by text' do @@ -264,7 +279,7 @@ feature 'Budget Investments' do fill_in "budget_investment_title", with: "search" within("div#js-suggest") do - expect(page).to have_content ("You are seeing 5 of 6 investments containing the term 'search'") + expect(page).to have_content "You are seeing 5 of 6 investments containing the term 'search'" end end @@ -279,7 +294,7 @@ feature 'Budget Investments' do fill_in "budget_investment_title", with: "item" within('div#js-suggest') do - expect(page).to_not have_content ('You are seeing') + expect(page).to_not have_content 'You are seeing' end end @@ -294,7 +309,7 @@ feature 'Budget Investments' do fill_in "budget_investment_title", with: "search" within('div#js-suggest') do - expect(page).to_not have_content ('You are seeing') + expect(page).to_not have_content 'You are seeing' end end end @@ -449,16 +464,35 @@ feature 'Budget Investments' do it_behaves_like "followable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" } - it_behaves_like "documentable", "budget_investment", "budget_investment_path", {"budget_id": "budget_id", "id": "id"} + it_behaves_like "imageable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" } - it_behaves_like "nested documentable", + it_behaves_like "nested imageable", "budget_investment", "new_budget_investment_path", { "budget_id": "budget_id" }, - "fill_new_valid_budget_investment", + "imageable_fill_new_valid_budget_investment", "Create Investment", "Budget Investment created successfully." + it_behaves_like "documentable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" } + + it_behaves_like "nested documentable", + "user", + "budget_investment", + "new_budget_investment_path", + { "budget_id": "budget_id" }, + "documentable_fill_new_valid_budget_investment", + "Create Investment", + "Budget Investment created successfully." + + it_behaves_like "mappable", + "budget_investment", + "investment", + "new_budget_investment_path", + "", + "budget_investment_path", + { "budget_id": "budget_id" } + context "Destroy" do scenario "Admin cannot destroy budget investments" do diff --git a/spec/features/campaigns_spec.rb b/spec/features/campaigns_spec.rb index 6dba2ff09..6e9897a6f 100644 --- a/spec/features/campaigns_spec.rb +++ b/spec/features/campaigns_spec.rb @@ -27,7 +27,7 @@ feature 'Email campaigns' do visit admin_stats_path expect(page).to have_content "#{@campaign1.name} (1)" - expect(page).to_not have_content (@campaign2.name).to_s + expect(page).to_not have_content @campaign2.name.to_s end end \ No newline at end of file diff --git a/spec/features/comments/polls_spec.rb b/spec/features/comments/polls_spec.rb new file mode 100644 index 000000000..0fe01cf06 --- /dev/null +++ b/spec/features/comments/polls_spec.rb @@ -0,0 +1,522 @@ +require 'rails_helper' +include ActionView::Helpers::DateHelper + +feature 'Commenting polls' do + let(:user) { create :user } + let(:poll) { create :poll } + + scenario 'Index' do + 3.times { create(:comment, commentable: poll) } + + visit poll_path(poll) + + expect(page).to have_css('.comment', count: 3) + + comment = Comment.last + within first('.comment') do + expect(page).to have_content comment.user.name + expect(page).to have_content I18n.l(comment.created_at, format: :datetime) + expect(page).to have_content comment.body + end + end + + scenario 'Show' do + skip "Feature not implemented yet, review soon" + + parent_comment = create(:comment, commentable: poll) + first_child = create(:comment, commentable: poll, parent: parent_comment) + second_child = create(:comment, commentable: poll, parent: parent_comment) + + visit comment_path(parent_comment) + + expect(page).to have_css(".comment", count: 3) + expect(page).to have_content parent_comment.body + expect(page).to have_content first_child.body + expect(page).to have_content second_child.body + expect(page).to have_link "Go back to #{poll.name}", href: poll_path(poll) + + expect(page).to have_selector("ul#comment_#{parent_comment.id}>li", count: 2) + expect(page).to have_selector("ul#comment_#{first_child.id}>li", count: 1) + expect(page).to have_selector("ul#comment_#{second_child.id}>li", count: 1) + end + + scenario 'Collapsable comments', :js do + parent_comment = create(:comment, body: "Main comment", commentable: poll) + child_comment = create(:comment, body: "First subcomment", commentable: poll, parent: parent_comment) + grandchild_comment = create(:comment, body: "Last subcomment", commentable: poll, parent: child_comment) + + visit poll_path(poll) + + expect(page).to have_css('.comment', count: 3) + + find("#comment_#{child_comment.id}_children_arrow").trigger('click') + + expect(page).to have_css('.comment', count: 2) + expect(page).to_not have_content grandchild_comment.body + + find("#comment_#{child_comment.id}_children_arrow").trigger('click') + + expect(page).to have_css('.comment', count: 3) + expect(page).to have_content grandchild_comment.body + + find("#comment_#{parent_comment.id}_children_arrow").trigger('click') + + expect(page).to have_css('.comment', count: 1) + expect(page).to_not have_content child_comment.body + expect(page).to_not have_content grandchild_comment.body + end + + scenario 'Comment order' do + c1 = create(:comment, :with_confidence_score, commentable: poll, cached_votes_up: 100, + cached_votes_total: 120, created_at: Time.current - 2) + c2 = create(:comment, :with_confidence_score, commentable: poll, cached_votes_up: 10, + cached_votes_total: 12, created_at: Time.current - 1) + c3 = create(:comment, :with_confidence_score, commentable: poll, cached_votes_up: 1, + cached_votes_total: 2, created_at: Time.current) + + visit poll_path(poll, order: :most_voted) + + expect(c1.body).to appear_before(c2.body) + expect(c2.body).to appear_before(c3.body) + + visit poll_path(poll, order: :newest) + + expect(c3.body).to appear_before(c2.body) + expect(c2.body).to appear_before(c1.body) + + visit poll_path(poll, order: :oldest) + + expect(c1.body).to appear_before(c2.body) + expect(c2.body).to appear_before(c3.body) + end + + scenario 'Creation date works differently in roots and in child comments, when sorting by confidence_score' do + old_root = create(:comment, commentable: poll, created_at: Time.current - 10) + new_root = create(:comment, commentable: poll, created_at: Time.current) + old_child = create(:comment, commentable: poll, parent_id: new_root.id, created_at: Time.current - 10) + new_child = create(:comment, commentable: poll, parent_id: new_root.id, created_at: Time.current) + + visit poll_path(poll, order: :most_voted) + + expect(new_root.body).to appear_before(old_root.body) + expect(old_child.body).to appear_before(new_child.body) + + visit poll_path(poll, order: :newest) + + expect(new_root.body).to appear_before(old_root.body) + expect(new_child.body).to appear_before(old_child.body) + + visit poll_path(poll, order: :oldest) + + expect(old_root.body).to appear_before(new_root.body) + expect(old_child.body).to appear_before(new_child.body) + end + + scenario 'Turns links into html links' do + create :comment, commentable: poll, body: 'Built with http://rubyonrails.org/' + + visit poll_path(poll) + + within first('.comment') do + expect(page).to have_content 'Built with http://rubyonrails.org/' + expect(page).to have_link('http://rubyonrails.org/', href: 'http://rubyonrails.org/') + expect(find_link('http://rubyonrails.org/')[:rel]).to eq('nofollow') + expect(find_link('http://rubyonrails.org/')[:target]).to eq('_blank') + end + end + + scenario 'Sanitizes comment body for security' do + create :comment, commentable: poll, + body: " click me http://www.url.com" + + visit poll_path(poll) + + within first('.comment') do + expect(page).to have_content "click me http://www.url.com" + expect(page).to have_link('http://www.url.com', href: 'http://www.url.com') + expect(page).not_to have_link('click me') + end + end + + scenario 'Paginated comments' do + per_page = 10 + (per_page + 2).times { create(:comment, commentable: poll)} + + visit poll_path(poll) + + expect(page).to have_css('.comment', count: per_page) + within("ul.pagination") do + expect(page).to have_content("1") + expect(page).to have_content("2") + expect(page).to_not have_content("3") + click_link "Next", exact: false + end + + expect(page).to have_css('.comment', count: 2) + end + + feature 'Not logged user' do + scenario 'can not see comments forms' do + create(:comment, commentable: poll) + visit poll_path(poll) + + expect(page).to have_content 'You must Sign in or Sign up to leave a comment' + within('#comments') do + expect(page).to_not have_content 'Write a comment' + expect(page).to_not have_content 'Reply' + end + end + end + + scenario 'Create', :js do + login_as(user) + visit poll_path(poll) + + fill_in "comment-body-poll_#{poll.id}", with: 'Have you thought about...?' + click_button 'Publish comment' + + within "#comments" do + expect(page).to have_content 'Have you thought about...?' + end + + within "#tab-comments-label" do + expect(page).to have_content 'Comments (1)' + end + end + + scenario 'Errors on create', :js do + login_as(user) + visit poll_path(poll) + + click_button 'Publish comment' + + expect(page).to have_content "Can't be blank" + end + + scenario 'Reply', :js do + citizen = create(:user, username: 'Ana') + manuela = create(:user, username: 'Manuela') + comment = create(:comment, commentable: poll, user: citizen) + + login_as(manuela) + visit poll_path(poll) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + fill_in "comment-body-comment_#{comment.id}", with: 'It will be done next week.' + click_button 'Publish reply' + end + + within "#comment_#{comment.id}" do + expect(page).to have_content 'It will be done next week.' + end + + expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true) + end + + scenario 'Errors on reply', :js do + comment = create(:comment, commentable: poll, user: user) + + login_as(user) + visit poll_path(poll) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + click_button 'Publish reply' + expect(page).to have_content "Can't be blank" + end + + end + + scenario "N replies", :js do + parent = create(:comment, commentable: poll) + + 7.times do + create(:comment, commentable: poll, parent: parent) + parent = parent.children.first + end + + visit poll_path(poll) + expect(page).to have_css(".comment.comment.comment.comment.comment.comment.comment.comment") + end + + scenario "Flagging as inappropriate", :js do + skip "Feature not implemented yet, review soon" + + comment = create(:comment, commentable: poll) + + login_as(user) + visit poll_path(poll) + + within "#comment_#{comment.id}" do + page.find("#flag-expand-comment-#{comment.id}").click + page.find("#flag-comment-#{comment.id}").click + + expect(page).to have_css("#unflag-expand-comment-#{comment.id}") + end + + expect(Flag.flagged?(user, comment)).to be + end + + scenario "Undoing flagging as inappropriate", :js do + skip "Feature not implemented yet, review soon" + + comment = create(:comment, commentable: poll) + Flag.flag(user, comment) + + login_as(user) + visit poll_path(poll) + + within "#comment_#{comment.id}" do + page.find("#unflag-expand-comment-#{comment.id}").click + page.find("#unflag-comment-#{comment.id}").click + + expect(page).to have_css("#flag-expand-comment-#{comment.id}") + end + + expect(Flag.flagged?(user, comment)).to_not be + end + + scenario "Flagging turbolinks sanity check", :js do + skip "Feature not implemented yet, review soon" + + poll = create(:poll, title: "Should we change the world?") + comment = create(:comment, commentable: poll) + + login_as(user) + visit polls_path + click_link "Should we change the world?" + + within "#comment_#{comment.id}" do + page.find("#flag-expand-comment-#{comment.id}").click + expect(page).to have_selector("#flag-comment-#{comment.id}") + end + end + + scenario "Erasing a comment's author" do + poll = create(:poll) + comment = create(:comment, commentable: poll, body: "this should be visible") + comment.user.erase + + visit poll_path(poll) + within "#comment_#{comment.id}" do + expect(page).to have_content('User deleted') + expect(page).to have_content('this should be visible') + end + end + + feature "Moderators" do + + scenario "can create comment as a moderator", :js do + skip "Feature not implemented yet, review soon" + + moderator = create(:moderator) + + login_as(moderator.user) + visit poll_path(poll) + + fill_in "comment-body-poll_#{poll.id}", with: "I am moderating!" + check "comment-as-moderator-poll_#{poll.id}" + click_button "Publish comment" + + within "#comments" do + expect(page).to have_content "I am moderating!" + expect(page).to have_content "Moderator ##{moderator.id}" + expect(page).to have_css "div.is-moderator" + expect(page).to have_css "img.moderator-avatar" + end + end + + scenario "can create reply as a moderator", :js do + skip "Feature not implemented yet, review soon" + + citizen = create(:user, username: "Ana") + manuela = create(:user, username: "Manuela") + moderator = create(:moderator, user: manuela) + comment = create(:comment, commentable: poll, user: citizen) + + login_as(manuela) + visit poll_path(poll) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + fill_in "comment-body-comment_#{comment.id}", with: "I am moderating!" + check "comment-as-moderator-comment_#{comment.id}" + click_button 'Publish reply' + end + + within "#comment_#{comment.id}" do + expect(page).to have_content "I am moderating!" + expect(page).to have_content "Moderator ##{moderator.id}" + expect(page).to have_css "div.is-moderator" + expect(page).to have_css "img.moderator-avatar" + end + + expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true) + end + + scenario "can not comment as an administrator" do + skip "Feature not implemented yet, review soon" + + moderator = create(:moderator) + + login_as(moderator.user) + visit poll_path(poll) + + expect(page).to_not have_content "Comment as administrator" + end + end + + feature "Administrators" do + scenario "can create comment as an administrator", :js do + skip "Feature not implemented yet, review soon" + + admin = create(:administrator) + + login_as(admin.user) + visit poll_path(poll) + + fill_in "comment-body-poll_#{poll.id}", with: "I am your Admin!" + check "comment-as-administrator-poll_#{poll.id}" + click_button "Publish comment" + + within "#comments" do + expect(page).to have_content "I am your Admin!" + expect(page).to have_content "Administrator ##{admin.id}" + expect(page).to have_css "div.is-admin" + expect(page).to have_css "img.admin-avatar" + end + end + + scenario "can create reply as an administrator", :js do + skip "Feature not implemented yet, review soon" + + citizen = create(:user, username: "Ana") + manuela = create(:user, username: "Manuela") + admin = create(:administrator, user: manuela) + comment = create(:comment, commentable: poll, user: citizen) + + login_as(manuela) + visit poll_path(poll) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + fill_in "comment-body-comment_#{comment.id}", with: "Top of the world!" + check "comment-as-administrator-comment_#{comment.id}" + click_button 'Publish reply' + end + + within "#comment_#{comment.id}" do + expect(page).to have_content "Top of the world!" + expect(page).to have_content "Administrator ##{admin.id}" + expect(page).to have_css "div.is-admin" + expect(page).to have_css "img.admin-avatar" + end + + expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true) + end + + scenario "can not comment as a moderator" do + skip "Feature not implemented yet, review soon" + + admin = create(:administrator) + + login_as(admin.user) + visit poll_path(poll) + + expect(page).to_not have_content "Comment as moderator" + end + end + + feature 'Voting comments' do + + background do + @manuela = create(:user, verified_at: Time.current) + @pablo = create(:user) + @poll = create(:poll) + @comment = create(:comment, commentable: @poll) + + login_as(@manuela) + end + + scenario 'Show' do + create(:vote, voter: @manuela, votable: @comment, vote_flag: true) + create(:vote, voter: @pablo, votable: @comment, vote_flag: false) + + visit poll_path(@poll) + + within("#comment_#{@comment.id}_votes") do + within(".in_favor") do + expect(page).to have_content "1" + end + + within(".against") do + expect(page).to have_content "1" + end + + expect(page).to have_content "2 votes" + end + end + + scenario 'Create', :js do + visit poll_path(@poll) + + within("#comment_#{@comment.id}_votes") do + find(".in_favor a").click + + within(".in_favor") do + expect(page).to have_content "1" + end + + within(".against") do + expect(page).to have_content "0" + end + + expect(page).to have_content "1 vote" + end + end + + scenario 'Update', :js do + visit poll_path(@poll) + + within("#comment_#{@comment.id}_votes") do + find('.in_favor a').click + find('.against a').click + + within('.in_favor') do + expect(page).to have_content "0" + end + + within('.against') do + expect(page).to have_content "1" + end + + expect(page).to have_content "1 vote" + end + end + + scenario 'Trying to vote multiple times', :js do + visit poll_path(@poll) + + within("#comment_#{@comment.id}_votes") do + find('.in_favor a').click + find('.in_favor a').click + + within('.in_favor') do + expect(page).to have_content "1" + end + + within('.against') do + expect(page).to have_content "0" + end + + expect(page).to have_content "1 vote" + end + end + end + +end diff --git a/spec/features/debates_spec.rb b/spec/features/debates_spec.rb index 749c7a373..39cd84760 100644 --- a/spec/features/debates_spec.rb +++ b/spec/features/debates_spec.rb @@ -66,7 +66,7 @@ feature 'Debates' do first(:link, debate.title).click link_text = find_link('Go back')[:href] - expect(link_text).to include(debates_path order: :hot_score, page: 1) + expect(link_text).to include(debates_path(order: :hot_score, page: 1)) end context "Show" do @@ -219,7 +219,7 @@ feature 'Debates' do visit edit_debate_path(debate) expect(current_path).not_to eq(edit_debate_path(debate)) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to carry out the action 'edit' on debate." end @@ -234,7 +234,7 @@ feature 'Debates' do visit edit_debate_path(debate) expect(current_path).not_to eq(edit_debate_path(debate)) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content 'You do not have permission to' end @@ -351,6 +351,69 @@ feature 'Debates' do expect(current_url).to include('order=created_at') expect(current_url).to include('page=1') end + + context 'Recommendations' do + + background do + Setting['feature.user.recommendations'] = true + create(:debate, title: 'Best', cached_votes_total: 10, tag_list: "Sport") + create(:debate, title: 'Medium', cached_votes_total: 5, tag_list: "Sport") + create(:debate, title: 'Worst', cached_votes_total: 1, tag_list: "Sport") + end + + after do + Setting['feature.user.recommendations'] = nil + end + + scenario 'Debates can not ordered by recommendations when there is not an user logged', :js do + visit debates_path + + expect(page).not_to have_selector('a', text: 'recommendations') + end + + scenario 'Should display text when there are not recommendeds results', :js do + user = create(:user) + proposal = create(:proposal, tag_list: "Distinct_to_sport") + create(:follow, followable: proposal, user: user) + login_as(user) + visit debates_path + + click_link 'recommendations' + + expect(page).to have_content "There are not debates related to your interests" + end + + scenario 'Should display text when user has not related interests', :js do + user = create(:user) + login_as(user) + visit debates_path + + click_link 'recommendations' + + expect(page).to have_content "Follow proposals so we can give you recommendations" + end + + scenario 'Debates are ordered by recommendations when there is a user logged', :js do + proposal = create(:proposal, tag_list: "Sport") + user = create(:user) + create(:follow, followable: proposal, user: user) + login_as(user) + + visit debates_path + + click_link 'recommendations' + + expect(page).to have_selector('a.active', text: 'recommendations') + + within '#debates' do + expect('Best').to appear_before('Medium') + expect('Medium').to appear_before('Worst') + end + + expect(current_url).to include('order=recommendations') + expect(current_url).to include('page=1') + end + end end context "Search" do @@ -759,6 +822,32 @@ feature 'Debates' do end end + scenario "Reorder by recommendations results maintaing search", :js do + Setting['feature.user.recommendations'] = true + user = create(:user) + login_as(user) + debate1 = create(:debate, title: "Show you got", cached_votes_total: 10, tag_list: "Sport") + debate2 = create(:debate, title: "Show what you got", cached_votes_total: 1, tag_list: "Sport") + debate3 = create(:debate, title: "Do not display with same tag", cached_votes_total: 100, tag_list: "Sport") + debate4 = create(:debate, title: "Do not display", cached_votes_total: 1) + proposal1 = create(:proposal, tag_list: "Sport") + create(:follow, followable: proposal1, user: user) + + visit debates_path + fill_in "search", with: "Show you got" + click_button "Search" + click_link 'recommendations' + expect(page).to have_selector("a.active", text: "recommendations") + + within("#debates") do + expect(all(".debate")[0].text).to match "Show you got" + expect(all(".debate")[1].text).to match "Show what you got" + expect(page).to_not have_content "Do not display with same tag" + expect(page).to_not have_content "Do not display" + end + Setting['feature.user.recommendations'] = nil + end + scenario 'After a search do not show featured debates' do featured_debates = create_featured_debates debate = create(:debate, title: "Abcdefghi") @@ -879,7 +968,7 @@ feature 'Debates' do check "debate_terms_of_service" within('div#js-suggest') do - expect(page).to have_content ("You are seeing 5 of 6 debates containing the term 'debate'") + expect(page).to have_content "You are seeing 5 of 6 debates containing the term 'debate'" end end @@ -895,7 +984,7 @@ feature 'Debates' do check "debate_terms_of_service" within('div#js-suggest') do - expect(page).to_not have_content ('You are seeing') + expect(page).to_not have_content 'You are seeing' end end end diff --git a/spec/features/emails_spec.rb b/spec/features/emails_spec.rb index af7674101..74b608ed6 100644 --- a/spec/features/emails_spec.rb +++ b/spec/features/emails_spec.rb @@ -335,9 +335,9 @@ feature 'Emails' do reset_mailer budget.email_selected - expect(find_email investment1.author.email).to be - expect(find_email investment2.author.email).to be - expect(find_email investment3.author.email).to_not be + expect(find_email(investment1.author.email)).to be + expect(find_email(investment2.author.email)).to be + expect(find_email(investment3.author.email)).to_not be email = open_last_email investment = investment2 @@ -358,9 +358,9 @@ feature 'Emails' do reset_mailer budget.email_unselected - expect(find_email investment1.author.email).to be - expect(find_email investment2.author.email).to be - expect(find_email investment3.author.email).to_not be + expect(find_email(investment1.author.email)).to be + expect(find_email(investment2.author.email)).to be + expect(find_email(investment3.author.email)).to_not be email = open_last_email investment = investment2 @@ -371,6 +371,54 @@ feature 'Emails' do end + context "Polls" do + + scenario "Do not send email on poll comment", :js do + user1 = create(:user, email_on_comment: true) + user2 = create(:user) + + poll = create(:poll, author: user1) + reset_mailer + + login_as(user2) + visit poll_path(poll) + + fill_in "comment-body-poll_#{poll.id}", with: 'Have you thought about...?' + click_button 'Publish comment' + + expect(page).to have_content 'Have you thought about...?' + + expect { open_last_email }.to raise_error "No email has been sent!" + end + + scenario "Send email on poll comment reply", :js do + user1 = create(:user, email_on_comment_reply: true) + user2 = create(:user) + + poll = create(:poll) + comment = create(:comment, commentable: poll, author: user1) + + login_as(user2) + visit poll_path(poll) + + click_link "Reply" + within "#js-comment-form-comment_#{comment.id}" do + fill_in "comment-body-comment_#{comment.id}", with: 'It will be done next week.' + click_button 'Publish reply' + end + expect(page).to have_content 'It will be done next week.' + + email = open_last_email + expect(email).to have_subject('Someone has responded to your comment') + expect(email).to deliver_to(user1) + expect(email).to_not have_body_text(poll_path(poll)) + expect(email).to have_body_text(comment_path(Comment.last)) + expect(email).to have_body_text(I18n.t("mailers.config.manage_email_subscriptions")) + expect(email).to have_body_text(account_path) + end + + end + context "Users without email" do scenario "should not receive emails", :js do user = create(:user, :verified, email_on_comment: true) diff --git a/spec/features/home_spec.rb b/spec/features/home_spec.rb index 4deed36bb..4854fff4d 100644 --- a/spec/features/home_spec.rb +++ b/spec/features/home_spec.rb @@ -3,20 +3,138 @@ require 'rails_helper' feature "Home" do feature "For not logged users" do + scenario 'Welcome message' do visit root_path expect(page).to have_content "Love the city, and it will become a city you love" end + + scenario 'Not display recommended section' do + debate = create(:debate) + + visit root_path + + expect(page).not_to have_content "Recommendations that may interest you" + end + end feature "For signed in users" do - scenario 'Redirect to proposals' do - login_as(create(:user)) - visit root_path - expect(current_path).to eq proposals_path + feature "Recommended" do + + background do + Setting['feature.user.recommendations'] = true + user = create(:user) + proposal = create(:proposal, tag_list: "Sport") + create(:follow, followable: proposal, user: user) + login_as(user) + end + + after do + Setting['feature.user.recommendations'] = nil + end + + scenario 'Display recommended section' do + debate = create(:debate, tag_list: "Sport") + visit root_path + expect(page).to have_content "Recommendations that may interest you" + end + + scenario 'Display recommended section when feature flag recommended is active' do + debate = create(:debate, tag_list: "Sport") + visit root_path + expect(page).to have_content "Recommendations that may interest you" + end + + scenario 'Not display recommended section when feature flag recommended is not active' do + debate = create(:debate, tag_list: "Sport") + Setting['feature.user.recommendations'] = false + + visit root_path + + expect(page).not_to have_content "Recommendations that may interest you" + end + + scenario 'Display debates' do + debate = create(:debate, tag_list: "Sport") + + visit root_path + + expect(page).to have_content debate.title + expect(page).to have_content debate.description + end + + scenario 'Display all recommended debates link' do + debate = create(:debate, tag_list: "Sport") + visit root_path + expect(page).to have_link("All recommended debates", href: debates_path(order: "recommendations")) + end + + scenario 'Display proposal' do + proposal = create(:proposal, tag_list: "Sport") + + visit root_path + + expect(page).to have_content proposal.title + expect(page).to have_content proposal.description + end + + scenario 'Display all recommended proposals link' do + debate = create(:proposal, tag_list: "Sport") + visit root_path + expect(page).to have_link("All recommended proposals", href: proposals_path(order: "recommendations")) + end + + scenario 'Display orbit carrousel' do + create_list(:debate, 3, tag_list: "Sport") + + visit root_path + + expect(page).to have_selector('li[data-slide="0"]') + expect(page).to have_selector('li[data-slide="1"]', visible: false) + expect(page).to have_selector('li[data-slide="2"]', visible: false) + end + + scenario 'Display recommended show when click on carousel' do + debate = create(:debate, tag_list: "Sport") + + visit root_path + click_on debate.title + + expect(current_path).to eq debate_path(debate) + end + + scenario 'Do not display recommended section when there are not debates and proposals' do + visit root_path + expect(page).not_to have_content "Recommendations that may interest you" + end + + feature 'Carousel size' do + + scenario 'Display debates centered when there are no proposals' do + debate = create(:debate, tag_list: "Sport") + visit root_path + expect(page).to have_selector('.medium-centered.large-centered') + end + + scenario 'Correct display debates and proposals' do + proposal = create(:proposal, tag_list: "Sport") + debates = create(:debate, tag_list: "Sport") + + visit root_path + + expect(page).to have_selector('.debates.medium-offset-2.large-offset-2') + expect(page).not_to have_selector('.proposals.medium-offset-2.large-offset-2') + expect(page).not_to have_selector('.debates.end') + expect(page).to have_selector('.proposals.end') + expect(page).not_to have_selector('.medium-centered.large-centered') + end + + end end + end feature 'IE alert' do diff --git a/spec/features/legislation/processes_spec.rb b/spec/features/legislation/processes_spec.rb index 0ef5e0c7c..e80e81dba 100644 --- a/spec/features/legislation/processes_spec.rb +++ b/spec/features/legislation/processes_spec.rb @@ -115,6 +115,14 @@ feature 'Legislation' do context 'process page' do context "show" do include_examples "not published permissions", :legislation_process_path + + scenario '#show view has document present' do + process = create(:legislation_process) + document = create(:document, documentable: process) + visit legislation_process_path(process) + + expect(page).to have_content(document.title) + end end context 'debate phase' do diff --git a/spec/features/management/managed_users_spec.rb b/spec/features/management/managed_users_spec.rb index ef3c539d9..68b9777a3 100644 --- a/spec/features/management/managed_users_spec.rb +++ b/spec/features/management/managed_users_spec.rb @@ -24,9 +24,9 @@ feature 'Managed User' do within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s - expect(page).to have_content (user.email).to_s - expect(page).to have_content (user.document_number).to_s + expect(page).to have_content user.username.to_s + expect(page).to have_content user.email.to_s + expect(page).to have_content user.document_number.to_s end end @@ -45,9 +45,9 @@ feature 'Managed User' do within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s - expect(page).to have_content (user.email).to_s - expect(page).to have_content (user.document_number).to_s + expect(page).to have_content user.username.to_s + expect(page).to have_content user.email.to_s + expect(page).to have_content user.document_number.to_s end end @@ -78,9 +78,9 @@ feature 'Managed User' do within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s - expect(page).to have_content (user.email).to_s - expect(page).to have_content (user.document_number).to_s + expect(page).to have_content user.username.to_s + expect(page).to have_content user.email.to_s + expect(page).to have_content user.document_number.to_s end end @@ -106,9 +106,9 @@ feature 'Managed User' do user = User.last within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s - expect(page).to have_content (user.email).to_s - expect(page).to have_content (user.document_number).to_s + expect(page).to have_content user.username.to_s + expect(page).to have_content user.email.to_s + expect(page).to have_content user.document_number.to_s end end @@ -134,8 +134,8 @@ feature 'Managed User' do user = User.last within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s - expect(page).to have_content (user.document_number).to_s + expect(page).to have_content user.username.to_s + expect(page).to have_content user.document_number.to_s end end end @@ -151,14 +151,14 @@ feature 'Managed User' do within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s + expect(page).to have_content user.username.to_s click_link "Change user" end expect(page).to have_content "User session signed out successfully." expect(page).to_not have_content "Identified as" - expect(page).to_not have_content (user.username).to_s + expect(page).to_not have_content user.username.to_s expect(current_path).to eq(management_root_path) end diff --git a/spec/features/management/proposals_spec.rb b/spec/features/management/proposals_spec.rb index 349a4f904..ed24de172 100644 --- a/spec/features/management/proposals_spec.rb +++ b/spec/features/management/proposals_spec.rb @@ -16,9 +16,9 @@ feature 'Proposals' do within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s - expect(page).to have_content (user.email).to_s - expect(page).to have_content (user.document_number).to_s + expect(page).to have_content user.username.to_s + expect(page).to have_content user.email.to_s + expect(page).to have_content user.document_number.to_s end fill_in 'proposal_title', with: 'Help refugees' @@ -119,9 +119,9 @@ feature 'Proposals' do within(".account-info") do expect(page).to have_content "Identified as" - expect(page).to have_content (user.username).to_s - expect(page).to have_content (user.email).to_s - expect(page).to have_content (user.document_number).to_s + expect(page).to have_content user.username.to_s + expect(page).to have_content user.email.to_s + expect(page).to have_content user.document_number.to_s end within(".proposals-list") do diff --git a/spec/features/management/users_spec.rb b/spec/features/management/users_spec.rb index f50728bfc..8060f33cb 100644 --- a/spec/features/management/users_spec.rb +++ b/spec/features/management/users_spec.rb @@ -29,7 +29,7 @@ feature 'Users' do expect(user).to be_level_three_verified expect(user).to be_residence_verified expect(user).to_not be_confirmed - expect(user.date_of_birth).to have_content (Date.new(1980, 12, 31)) + expect(user.date_of_birth).to have_content Date.new(1980, 12, 31) sent_token = /.*confirmation_token=(.*)".*/.match(ActionMailer::Base.deliveries.last.body.to_s)[1] visit user_confirmation_path(confirmation_token: sent_token) @@ -69,7 +69,7 @@ feature 'Users' do expect(user).to be_level_three_verified expect(user).to be_residence_verified expect(user).to be_confirmed - expect(user.date_of_birth).to have_content (Date.new(1980, 12, 31)) + expect(user.date_of_birth).to have_content Date.new(1980, 12, 31) end scenario 'Delete a level 2 user account from document verification page', :js do diff --git a/spec/features/moderation_spec.rb b/spec/features/moderation_spec.rb index fedcb105d..a39dc6477 100644 --- a/spec/features/moderation_spec.rb +++ b/spec/features/moderation_spec.rb @@ -11,7 +11,7 @@ feature 'Moderation' do visit moderation_root_path expect(current_path).not_to eq(moderation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -25,7 +25,7 @@ feature 'Moderation' do visit moderation_root_path expect(current_path).not_to eq(moderation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -39,7 +39,7 @@ feature 'Moderation' do visit moderation_root_path expect(current_path).not_to eq(moderation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -53,7 +53,7 @@ feature 'Moderation' do visit moderation_root_path expect(current_path).not_to eq(moderation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -93,17 +93,27 @@ feature 'Moderation' do expect(page).to_not have_link('Valuation') end - scenario 'Moderation dashboard' do - create(:moderator, user: user) - login_as(user) - visit root_path + context 'Moderation dashboard' do + background do + Setting['org_name'] = 'OrgName' + end - click_link 'Moderation' + after do + Setting['org_name'] = 'CONSUL' + end - expect(current_path).to eq(moderation_root_path) - expect(page).to have_css('#moderation_menu') - expect(page).to_not have_css('#admin_menu') - expect(page).to_not have_css('#valuation_menu') + scenario 'Contains correct elements' do + create(:moderator, user: user) + login_as(user) + visit root_path + + click_link 'Moderation' + + expect(page).to have_link('Go back to OrgName') + expect(current_path).to eq(moderation_root_path) + expect(page).to have_css('#moderation_menu') + expect(page).to_not have_css('#admin_menu') + expect(page).to_not have_css('#valuation_menu') + end end - end diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb index 7b044e18a..fee0da813 100644 --- a/spec/features/notifications_spec.rb +++ b/spec/features/notifications_spec.rb @@ -14,17 +14,14 @@ feature "Notifications" do let(:legislation_question) { create(:legislation_question, process: process, author: administrator) } let(:legislation_annotation) { create(:legislation_annotation, author: author) } + let(:topic) do + proposal = create(:proposal) + community = proposal.community + create(:topic, community: community, author: author) + end + scenario "User commented on my debate", :js do - login_as user - visit debate_path debate - - fill_in "comment-body-debate_#{debate.id}", with: "I commented on your debate" - click_button "Publish comment" - within "#comments" do - expect(page).to have_content "I commented on your debate" - end - - logout + create(:notification, notifiable: debate, user: author) login_as author visit root_path @@ -37,17 +34,7 @@ feature "Notifications" do end scenario "User commented on my legislation question", :js do - verified_user = create(:user, :level_two) - login_as verified_user - visit legislation_process_question_path legislation_question.process, legislation_question - - fill_in "comment-body-legislation_question_#{legislation_question.id}", with: "I answered your question" - click_button "Publish answer" - within "#comments" do - expect(page).to have_content "I answered your question" - end - - logout + create(:notification, notifiable: legislation_question, user: administrator) login_as administrator visit root_path @@ -59,6 +46,19 @@ feature "Notifications" do expect(page).to have_xpath "//a[@href='#{notification_path(Notification.last)}']" end + scenario "User commented on my topic", :js do + create(:notification, notifiable: topic, user: author) + login_as author + visit root_path + + find(".icon-notification").click + + expect(page).to have_css ".notification", count: 1 + + expect(page).to have_content "Someone commented on" + expect(page).to have_xpath "//a[@href='#{notification_path(Notification.last)}']" + end + scenario "Multiple comments on my proposal", :js do login_as user visit proposal_path proposal @@ -82,6 +82,7 @@ feature "Notifications" do logout login_as author visit root_path + visit root_path find(".icon-notification").click @@ -107,8 +108,10 @@ feature "Notifications" do end logout + login_as author visit root_path + visit root_path find(".icon-notification").click @@ -137,6 +140,7 @@ feature "Notifications" do login_as author visit root_path + visit root_path find(".icon-notification").click @@ -208,6 +212,7 @@ feature "Notifications" do logout login_as user1 visit root_path + visit root_path find(".icon-notification").click @@ -219,6 +224,7 @@ feature "Notifications" do logout login_as user2 visit root_path + visit root_path find(".icon-notification").click @@ -230,6 +236,7 @@ feature "Notifications" do logout login_as user3 visit root_path + visit root_path find(".icon-no-notification").click diff --git a/spec/features/officing/results_spec.rb b/spec/features/officing/results_spec.rb index 835903ab9..252d4edd6 100644 --- a/spec/features/officing/results_spec.rb +++ b/spec/features/officing/results_spec.rb @@ -7,8 +7,13 @@ feature 'Officing Results' do @officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer) @poll = @officer_assignment.booth_assignment.poll @poll.update(ends_at: 1.day.ago) - @question_1 = create(:poll_question, poll: @poll, valid_answers: "Yes,No") - @question_2 = create(:poll_question, poll: @poll, valid_answers: "Today,Tomorrow") + @question_1 = create(:poll_question, poll: @poll) + create(:poll_question_answer, title: 'Yes', question: @question_1) + create(:poll_question_answer, title: 'No', question: @question_1) + @question_2 = create(:poll_question, poll: @poll) + create(:poll_question_answer, title: 'Today', question: @question_2) + create(:poll_question_answer, title: 'Tomorrow', question: @question_2) + login_as(@poll_officer.user) end @@ -53,9 +58,7 @@ feature 'Officing Results' do expect(page).to_not have_content('Your results') booth_name = @officer_assignment.booth_assignment.booth.name - date = I18n.l(@poll.starts_at.to_date, format: :long) select booth_name, from: 'officer_assignment_id' - select date, from: 'date' fill_in "questions[#{@question_1.id}][0]", with: '100' fill_in "questions[#{@question_1.id}][1]", with: '200' @@ -71,8 +74,8 @@ feature 'Officing Results' do expect(page).to have_content('Your results') - within("#results_#{@officer_assignment.booth_assignment_id}_#{@poll.starts_at.to_date.strftime('%Y%m%d')}") do - expect(page).to have_content(date) + within("#results_#{@officer_assignment.booth_assignment_id}_#{Date.current.strftime('%Y%m%d')}") do + expect(page).to have_content(I18n.l(Date.current, format: :long)) expect(page).to have_content(booth_name) end end @@ -81,9 +84,9 @@ feature 'Officing Results' do partial_result = create(:poll_partial_result, officer_assignment: @officer_assignment, booth_assignment: @officer_assignment.booth_assignment, - date: @poll.starts_at, + date: Date.current, question: @question_1, - answer: @question_1.valid_answers[0], + answer: @question_1.question_answers.first.title, author: @poll_officer.user, amount: 7777) @@ -94,9 +97,7 @@ feature 'Officing Results' do visit new_officing_poll_result_path(@poll) booth_name = partial_result.booth_assignment.booth.name - date = I18n.l(partial_result.date, format: :long) select booth_name, from: 'officer_assignment_id' - select date, from: 'date' fill_in "questions[#{@question_1.id}][0]", with: '5555' fill_in "questions[#{@question_1.id}][1]", with: '200' @@ -127,21 +128,13 @@ feature 'Officing Results' do date: @poll.ends_at, question: @question_1, amount: 33) - white_result = create(:poll_white_result, + poll_recount = create(:poll_recount, officer_assignment: @officer_assignment, booth_assignment: @officer_assignment.booth_assignment, date: @poll.ends_at, - amount: 21) - null_result = create(:poll_null_result, - officer_assignment: @officer_assignment, - booth_assignment: @officer_assignment.booth_assignment, - date: @poll.ends_at, - amount: 44) - total_result = create(:poll_total_result, - officer_assignment: @officer_assignment, - booth_assignment: @officer_assignment.booth_assignment, - date: @poll.ends_at, - amount: 66) + white_amount: 21, + null_amount: 44, + total_amount: 66) visit officing_poll_results_path(@poll, date: I18n.l(@poll.ends_at.to_date), @@ -151,13 +144,13 @@ feature 'Officing Results' do expect(page).to have_content(@officer_assignment.booth_assignment.booth.name) expect(page).to have_content(@question_1.title) - @question_1.valid_answers.each_with_index do |answer, i| - within("#question_#{@question_1.id}_#{i}_result") { expect(page).to have_content(answer) } + @question_1.question_answers.each_with_index do |answer, i| + within("#question_#{@question_1.id}_#{i}_result") { expect(page).to have_content(answer.title) } end expect(page).to have_content(@question_2.title) - @question_2.valid_answers.each_with_index do |answer, i| - within("#question_#{@question_2.id}_#{i}_result") { expect(page).to have_content(answer) } + @question_2.question_answers.each_with_index do |answer, i| + within("#question_#{@question_2.id}_#{i}_result") { expect(page).to have_content(answer.title) } end within('#white_results') { expect(page).to have_content('21') } diff --git a/spec/features/officing/voters_spec.rb b/spec/features/officing/voters_spec.rb index 0a23a6a27..2c4b17d37 100644 --- a/spec/features/officing/voters_spec.rb +++ b/spec/features/officing/voters_spec.rb @@ -2,16 +2,19 @@ require 'rails_helper' feature 'Voters' do + let(:poll) { create(:poll, :current) } + let(:booth) { create(:poll_booth) } let(:officer) { create(:poll_officer) } background do login_as(officer.user) create(:geozone, :in_census) + create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection) + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment) end scenario "Can vote", :js do - poll = create(:poll_officer_assignment, officer: officer).booth_assignment.poll - visit new_officing_residence_path officing_verify_residence @@ -26,18 +29,21 @@ feature 'Voters' do page.evaluate_script("window.location.reload()") expect(page).to have_content "Has already participated in this poll" expect(page).to_not have_button "Confirm vote" + + expect(Poll::Voter.last.officer_id).to eq(officer.id) end scenario "Already voted", :js do - poll1 = create(:poll) - poll2 = create(:poll) + poll2 = create(:poll, :current) + booth_assignment = create(:poll_booth_assignment, poll: poll2, booth: booth) + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment) user = create(:user, :level_two) - voter = create(:poll_voter, poll: poll1, user: user) + voter = create(:poll_voter, poll: poll, user: user) visit new_officing_voter_path(id: voter.user.id) - within("#poll_#{poll1.id}") do + within("#poll_#{poll.id}") do expect(page).to have_content "Has already participated in this poll" expect(page).to_not have_button "Confirm vote" end @@ -50,7 +56,6 @@ feature 'Voters' do scenario "Had already verified his residence, but is not level 2 yet", :js do user = create(:user, residence_verified_at: Time.current, document_type: "1", document_number: "12345678Z") expect(user).to_not be_level_two_verified - poll = create(:poll_officer_assignment, officer: officer).booth_assignment.poll visit new_officing_residence_path officing_verify_residence @@ -59,6 +64,37 @@ feature 'Voters' do expect(page).to have_content poll.name end - #Fix and use answerable_by(user) - xscenario "Display only answerable polls" + scenario "Display only current polls on which officer has a voting shift today, and user can answer", :js do + poll_current = create(:poll, :current) + second_booth = create(:poll_booth) + booth_assignment = create(:poll_booth_assignment, poll: poll_current, booth: second_booth) + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment) + create(:poll_shift, officer: officer, booth: second_booth, date: Date.current, task: :recount_scrutiny) + create(:poll_shift, officer: officer, booth: second_booth, date: Date.tomorrow, task: :vote_collection) + + poll_expired = create(:poll, :expired) + create(:poll_officer_assignment, officer: officer, booth_assignment: create(:poll_booth_assignment, poll: poll_expired, booth: booth)) + + poll_incoming = create(:poll, :incoming) + create(:poll_officer_assignment, officer: officer, booth_assignment: create(:poll_booth_assignment, poll: poll_incoming, booth: booth)) + + poll_geozone_restricted_in = create(:poll, :current, geozone_restricted: true, geozones: [Geozone.first]) + booth_assignment = create(:poll_booth_assignment, poll: poll_geozone_restricted_in, booth: booth) + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment) + + poll_geozone_restricted_out = create(:poll, :current, geozone_restricted: true, geozones: [create(:geozone, census_code: "02")]) + booth_assignment = create(:poll_booth_assignment, poll: poll_geozone_restricted_out, booth: booth) + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment) + + visit new_officing_residence_path + officing_verify_residence + + expect(page).to have_content "Polls" + expect(page).to have_content poll.name + expect(page).not_to have_content poll_current.name + expect(page).not_to have_content poll_expired.name + expect(page).not_to have_content poll_incoming.name + expect(page).to have_content poll_geozone_restricted_in.name + expect(page).not_to have_content poll_geozone_restricted_out.name + end end diff --git a/spec/features/officing_spec.rb b/spec/features/officing_spec.rb index d4cb416a1..b208b735c 100644 --- a/spec/features/officing_spec.rb +++ b/spec/features/officing_spec.rb @@ -1,4 +1,5 @@ require 'rails_helper' +require 'sessions_helper' feature 'Poll Officing' do let(:user) { create(:user) } @@ -11,7 +12,7 @@ feature 'Poll Officing' do visit officing_root_path expect(current_path).not_to eq(officing_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -24,7 +25,7 @@ feature 'Poll Officing' do visit officing_root_path expect(current_path).not_to eq(officing_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -37,7 +38,7 @@ feature 'Poll Officing' do visit officing_root_path expect(current_path).not_to eq(officing_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -50,11 +51,26 @@ feature 'Poll Officing' do visit officing_root_path expect(current_path).not_to eq(officing_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end - scenario 'Access as an poll officer is authorized' do + scenario 'Access as an administrator is not authorized' do + create(:administrator, user: user) + create(:poll) + login_as(user) + visit root_path + + expect(page).to_not have_link("Polling officers") + visit officing_root_path + + expect(current_path).not_to eq(officing_root_path) + expect(current_path).to eq(root_path) + expect(page).to have_content "You do not have permission to access this page" + end + + scenario 'Access as an administrator with poll officer role is authorized' do + create(:administrator, user: user) create(:poll_officer, user: user) create(:poll) login_as(user) @@ -67,8 +83,8 @@ feature 'Poll Officing' do expect(page).to_not have_content "You do not have permission to access this page" end - scenario 'Access as an administrator is authorized' do - create(:administrator, user: user) + scenario 'Access as an poll officer is authorized' do + create(:poll_officer, user: user) create(:poll) login_as(user) visit root_path @@ -106,4 +122,64 @@ feature 'Poll Officing' do expect(page).to_not have_css('#moderation_menu') end -end \ No newline at end of file + scenario 'Officing dashboard available for multiple sessions', :js do + poll = create(:poll) + booth = create(:poll_booth) + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + + user1 = create(:user) + user2 = create(:user) + officer1 = create(:poll_officer, user: user1) + officer2 = create(:poll_officer, user: user2) + + create(:poll_shift, officer: officer1, booth: booth, date: Date.current, task: :vote_collection) + create(:poll_shift, officer: officer2, booth: booth, date: Date.current, task: :vote_collection) + + officer_assignment_1 = create(:poll_officer_assignment, booth_assignment: booth_assignment, officer: officer1) + officer_assignment_2 = create(:poll_officer_assignment, booth_assignment: booth_assignment, officer: officer2) + + in_browser(:one) do + login_as user1 + visit officing_root_path + end + + in_browser(:two) do + login_as user2 + visit officing_root_path + end + + in_browser(:one) do + page.should have_content("Here you can validate user documents and store voting results") + + visit new_officing_residence_path + select 'DNI', from: 'residence_document_type' + fill_in 'residence_document_number', with: "12345678Z" + fill_in 'residence_year_of_birth', with: '1980' + click_button 'Validate document' + expect(page).to have_content 'Document verified with Census' + click_button "Confirm vote" + expect(page).to have_content "Vote introduced!" + expect(Poll::Voter.where(document_number: '12345678Z', poll_id: poll, origin: 'booth', officer_id: officer1).count).to be(1) + + visit final_officing_polls_path + page.should have_content("Polls ready for final recounting") + end + + in_browser(:two) do + page.should have_content("Here you can validate user documents and store voting results") + + visit new_officing_residence_path + select 'DNI', from: 'residence_document_type' + fill_in 'residence_document_number', with: "12345678Y" + fill_in 'residence_year_of_birth', with: '1980' + click_button 'Validate document' + expect(page).to have_content 'Document verified with Census' + click_button "Confirm vote" + expect(page).to have_content "Vote introduced!" + expect(Poll::Voter.where(document_number: '12345678Y', poll_id: poll, origin: 'booth', officer_id: officer2).count).to be(1) + + visit final_officing_polls_path + page.should have_content("Polls ready for final recounting") + end + end +end diff --git a/spec/features/polls/answers_spec.rb b/spec/features/polls/answers_spec.rb new file mode 100644 index 000000000..8bb87c94e --- /dev/null +++ b/spec/features/polls/answers_spec.rb @@ -0,0 +1,79 @@ +require 'rails_helper' + +feature 'Answers' do + + let(:question) { create(:poll_question) } + let(:admin) { create(:administrator) } + + background do + login_as(admin.user) + end + + scenario "Index" do + answer1 = create(:poll_question_answer, question: question, given_order: 2) + answer2 = create(:poll_question_answer, question: question, given_order: 1) + + visit admin_question_path(question) + + expect(page).to have_css(".poll_question_answer", count: 2) + expect(page.body.index(answer1.title)).to be < page.body.index(answer2.title) + + within("#poll_question_answer_#{answer1.id}") do + expect(page).to have_content answer1.title + expect(page).to have_content answer1.description + end + end + + scenario "Create" do + visit admin_question_path(question) + + click_link "Add answer" + fill_in "poll_question_answer_title", with: "¿Would you like to reform Central Park?" + fill_in "poll_question_answer_description", with: "Adding more trees, creating a play area..." + click_button "Save" + + expect(page).to have_content "Answer created successfully" + expect(page).to have_css(".poll_question_answer", count: 1) + expect(page).to have_content "¿Would you like to reform Central Park?" + expect(page).to have_content "Adding more trees, creating a play area..." + end + + scenario 'Add video to answer' do + answer1 = create(:poll_question_answer, question: question) + answer2 = create(:poll_question_answer, question: question) + + visit admin_question_path(question) + + within("#poll_question_answer_#{answer1.id}") do + click_link "Video list" + end + + click_link "Add video" + + fill_in "poll_question_answer_video_title", with: "Awesome project video" + fill_in "poll_question_answer_video_url", with: "https://www.youtube.com/watch?v=123" + + click_button "Save" + + within("#poll_question_answer_video_#{answer1.videos.last.id}") do + expect(page).to have_content "Awesome project video" + expect(page).to have_content "https://www.youtube.com/watch?v=123" + end + end + + pending "Update" + pending "Destroy" + + context "Gallery" do + + it_behaves_like "nested imageable", + "poll_question_answer", + "new_admin_answer_image_path", + { "answer_id": "id" }, + nil, + "Save image", + "Image uploaded successfully", + true + end + +end diff --git a/spec/features/polls/polls_spec.rb b/spec/features/polls/polls_spec.rb index 047c71146..8629a1087 100644 --- a/spec/features/polls/polls_spec.rb +++ b/spec/features/polls/polls_spec.rb @@ -6,11 +6,15 @@ feature 'Polls' do scenario 'Polls can be listed' do polls = create_list(:poll, 3) + create(:image, imageable: polls[0]) + create(:image, imageable: polls[1]) + create(:image, imageable: polls[2]) visit polls_path polls.each do |poll| expect(page).to have_content(poll.name) + expect(page).to have_css("img[alt='#{poll.image.title}']") expect(page).to have_link("Participate in this poll") end end @@ -55,11 +59,37 @@ feature 'Polls' do expect(page).to have_link('Incoming') expect(page).to_not have_link('Expired') end + + scenario "Poll title link to stats if enabled" do + poll = create(:poll, name: "Poll with stats", stats_enabled: true) + + visit polls_path + + expect(page).to have_link("Poll with stats", href: stats_poll_path(poll)) + end + + scenario "Poll title link to results if enabled" do + poll = create(:poll, name: "Poll with results", stats_enabled: true, results_enabled: true) + + visit polls_path + + expect(page).to have_link("Poll with results", href: results_poll_path(poll)) + end end context 'Show' do let(:geozone) { create(:geozone) } - let(:poll) { create(:poll) } + let(:poll) { create(:poll, summary: "Summary", description: "Description") } + + scenario 'Show answers with videos' do + question = create(:poll_question, poll: poll) + answer = create(:poll_question_answer, question: question, title: 'Chewbacca') + video = create(:poll_answer_video, answer: answer, title: "Awesome project video", url: "https://www.youtube.com/watch?v=123") + + visit poll_path(poll) + + expect(page).to have_link("Awesome project video", href: "https://www.youtube.com/watch?v=123") + end scenario 'Lists questions from proposals as well as regular ones' do normal_question = create(:poll_question, poll: poll) @@ -67,13 +97,42 @@ feature 'Polls' do visit poll_path(poll) expect(page).to have_content(poll.name) + expect(page).to have_content(poll.summary) + expect(page).to have_content(poll.description) expect(page).to have_content(normal_question.title) expect(page).to have_content(proposal_question.title) end + scenario "Question answers appear in the given order" do + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, title: 'First', question: question, given_order: 2) + answer2 = create(:poll_question_answer, title: 'Second', question: question, given_order: 1) + + visit poll_path(poll) + + within("div#poll_question_#{question.id}") do + expect(page.body.index(answer1.title)).to be < page.body.index(answer2.title) + end + end + + scenario "More info answers appear in the given order" do + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, title: 'First', question: question, given_order: 2) + answer2 = create(:poll_question_answer, title: 'Second', question: question, given_order: 1) + + visit poll_path(poll) + + within('div.poll-more-info-answers') do + expect(page.body.index(answer1.title)).to be < page.body.index(answer2.title) + end + end + scenario 'Non-logged in users' do - create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') + visit poll_path(poll) expect(page).to have_content('Han Solo') @@ -85,9 +144,16 @@ feature 'Polls' do end scenario 'Level 1 users' do + visit polls_path + expect(page).to_not have_selector('.already-answer') + poll.update(geozone_restricted: true) poll.geozones << geozone - create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') + login_as(create(:user, geozone: geozone)) visit poll_path(poll) @@ -103,7 +169,11 @@ feature 'Polls' do scenario 'Level 2 users in an incoming poll' do incoming_poll = create(:poll, :incoming, geozone_restricted: true) incoming_poll.geozones << geozone - create(:poll_question, poll: incoming_poll, valid_answers: 'Rey, Finn') + + question = create(:poll_question, poll: incoming_poll) + answer1 = create(:poll_question_answer, question: question, title: 'Rey') + answer2 = create(:poll_question_answer, question: question, title: 'Finn') + login_as(create(:user, :level_two, geozone: geozone)) visit poll_path(incoming_poll) @@ -119,7 +189,11 @@ feature 'Polls' do scenario 'Level 2 users in an expired poll' do expired_poll = create(:poll, :expired, geozone_restricted: true) expired_poll.geozones << geozone - create(:poll_question, poll: expired_poll, valid_answers: 'Luke, Leia') + + question = create(:poll_question, poll: expired_poll) + answer1 = create(:poll_question_answer, question: question, title: 'Luke') + answer2 = create(:poll_question_answer, question: question, title: 'Leia') + login_as(create(:user, :level_two, geozone: geozone)) visit poll_path(expired_poll) @@ -135,7 +209,11 @@ feature 'Polls' do scenario 'Level 2 users in a poll with questions for a geozone which is not theirs' do poll.update(geozone_restricted: true) poll.geozones << create(:geozone) - create(:poll_question, poll: poll, valid_answers: 'Vader, Palpatine') + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Vader') + answer2 = create(:poll_question_answer, question: question, title: 'Palpatine') + login_as(create(:user, :level_two)) visit poll_path(poll) @@ -149,7 +227,11 @@ feature 'Polls' do scenario 'Level 2 users reading a same-geozone poll' do poll.update(geozone_restricted: true) poll.geozones << geozone - create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') + login_as(create(:user, :level_two, geozone: geozone)) visit poll_path(poll) @@ -158,7 +240,10 @@ feature 'Polls' do end scenario 'Level 2 users reading a all-geozones poll' do - create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') + login_as(create(:user, :level_two)) visit poll_path(poll) @@ -167,7 +252,9 @@ feature 'Polls' do end scenario 'Level 2 users who have already answered' do - question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') user = create(:user, :level_two) create(:poll_answer, question: question, author: user, answer: 'Chewbacca') @@ -175,15 +262,19 @@ feature 'Polls' do visit poll_path(poll) expect(page).to have_link('Han Solo') - expect(page).to_not have_link('Chewbacca') - expect(page).to have_content('Chewbacca') + expect(page).to have_link('Chewbacca') end scenario 'Level 2 users answering', :js do poll.update(geozone_restricted: true) poll.geozones << geozone - create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') + user = create(:user, :level_two, geozone: geozone) + login_as user visit poll_path(poll) @@ -193,5 +284,173 @@ feature 'Polls' do expect(page).to have_link('Chewbacca') end + scenario 'Level 2 users changing answer', :js do + poll.update(geozone_restricted: true) + poll.geozones << geozone + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') + + user = create(:user, :level_two, geozone: geozone) + + login_as user + visit poll_path(poll) + + click_link 'Han Solo' + + expect(page).to_not have_link('Han Solo') + expect(page).to have_link('Chewbacca') + + click_link 'Chewbacca' + + expect(page).to_not have_link('Chewbacca') + expect(page).to have_link('Han Solo') + end + + scenario 'Level 2 votes, signs out, signs in, votes again', :js do + poll.update(geozone_restricted: true) + poll.geozones << geozone + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Han Solo') + answer2 = create(:poll_question_answer, question: question, title: 'Chewbacca') + + user = create(:user, :level_two, geozone: geozone) + + login_as user + visit poll_path(poll) + click_link 'Han Solo' + + expect(page).to_not have_link('Han Solo') + expect(page).to have_link('Chewbacca') + + click_link "Sign out" + login_as user + visit poll_path(poll) + click_link 'Han Solo' + + expect(page).to_not have_link('Han Solo') + expect(page).to have_link('Chewbacca') + + click_link "Sign out" + login_as user + visit poll_path(poll) + click_link 'Chewbacca' + + expect(page).to_not have_link('Chewbacca') + expect(page).to have_link('Han Solo') + end + end + + context 'Booth & Website' do + + let(:poll) { create(:poll, summary: "Summary", description: "Description") } + let(:booth) { create(:poll_booth) } + let(:officer) { create(:poll_officer) } + + scenario 'Already voted on booth cannot vote on website', :js do + + create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection) + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment) + question = create(:poll_question, poll: poll) + create(:poll_question_answer, question: question, title: 'Han Solo') + create(:poll_question_answer, question: question, title: 'Chewbacca') + user = create(:user, :level_two, :in_census) + + login_as(officer.user) + visit new_officing_residence_path + officing_verify_residence + click_button "Confirm vote" + + expect(page).to have_content "Vote introduced!" + + visit new_officing_residence_path + click_link "Sign out" + login_as user + visit poll_path(poll) + + expect(page).to have_content "You have already participated in a physical booth. You can not participate again." + + within("#poll_question_#{question.id}_answers") do + expect(page).to have_content('Han Solo') + expect(page).to have_content('Chewbacca') + + expect(page).to_not have_link('Han Solo') + expect(page).to_not have_link('Chewbacca') + end + end + + end + + context "Results and stats" do + scenario "Show poll results and stats if enabled and poll expired" do + poll = create(:poll, :expired, results_enabled: true, stats_enabled: true) + user = create(:user) + + login_as user + visit poll_path(poll) + + expect(page).to have_content("Poll results") + expect(page).to have_content("Participation statistics") + + visit results_poll_path(poll) + expect(page).to have_content("Questions") + + visit stats_poll_path(poll) + expect(page).to have_content("Participation data") + end + + scenario "Don't show poll results and stats if not enabled" do + poll = create(:poll, :expired, results_enabled: false, stats_enabled: false) + user = create(:user) + + login_as user + visit poll_path(poll) + + expect(page).to_not have_content("Poll results") + expect(page).to_not have_content("Participation statistics") + + visit results_poll_path(poll) + expect(page).to have_content("You do not have permission to carry out the action 'results' on poll.") + + visit stats_poll_path(poll) + expect(page).to have_content("You do not have permission to carry out the action 'stats' on poll.") + end + + scenario "Don't show poll results and stats if is not expired" do + poll = create(:poll, :current, results_enabled: true, stats_enabled: true) + user = create(:user) + + login_as user + visit poll_path(poll) + + expect(page).to_not have_content("Poll results") + expect(page).to_not have_content("Participation statistics") + + visit results_poll_path(poll) + expect(page).to have_content("You do not have permission to carry out the action 'results' on poll.") + + visit stats_poll_path(poll) + expect(page).to have_content("You do not have permission to carry out the action 'stats' on poll.") + end + + scenario "Show poll results and stats if user is administrator" do + poll = create(:poll, :current, results_enabled: false, stats_enabled: false) + user = create(:administrator).user + + login_as user + visit poll_path(poll) + + expect(page).to have_content("Poll results") + expect(page).to have_content("Participation statistics") + + visit results_poll_path(poll) + expect(page).to have_content("Questions") + + visit stats_poll_path(poll) + expect(page).to have_content("Participation data") + end end end diff --git a/spec/features/polls/questions_spec.rb b/spec/features/polls/questions_spec.rb index 1563ca81a..9e7efeedc 100644 --- a/spec/features/polls/questions_spec.rb +++ b/spec/features/polls/questions_spec.rb @@ -11,121 +11,4 @@ feature 'Poll Questions' do expect(proposal_question.title).to appear_before(normal_question.title) end - - scenario 'shows the author visible name instead of a link to the author' do - poll = create(:poll) - question_with_author = create(:poll_question, poll: poll) - question_with_author_visible_name = create(:poll_question, poll: poll, author_visible_name: 'potato') - - visit question_path(question_with_author) - expect(page).to have_link(question_with_author.author.name) - - visit question_path(question_with_author_visible_name) - expect(page).to_not have_link(question_with_author_visible_name.author.name) - expect(page).to have_content(question_with_author_visible_name.author_visible_name) - end - - scenario '#show view has video_url present' do - poll = create(:poll) - normal_question = create(:poll_question, poll: poll, video_url: "https://puppyvideos.com") - - visit question_path(normal_question) - - expect(page).to have_link(normal_question.video_url) - end - - scenario '#show view has document present' do - poll = create(:poll) - normal_question = create(:poll_question, poll: poll) - document = create(:document, documentable: normal_question) - - visit question_path(normal_question) - - expect(page).to have_content(document.title) - end - - context 'Answering' do - let(:geozone) { create(:geozone) } - let(:poll) { create(:poll, geozone_restricted: true, geozone_ids: [geozone.id]) } - - scenario 'Non-logged in users' do - question = create(:poll_question, valid_answers: 'Han Solo, Chewbacca') - - visit question_path(question) - - expect(page).to have_content('You must Sign in or Sign up to participate') - end - - scenario 'Level 1 users' do - question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') - - login_as(create(:user, geozone: geozone)) - visit question_path(question) - - expect(page).to have_content('You must verify your account in order to answer') - end - - scenario 'Level 2 users in an poll question for a geozone which is not theirs' do - - other_poll = create(:poll, geozone_restricted: true, geozone_ids: [create(:geozone).id]) - question = create(:poll_question, poll: other_poll, valid_answers: 'Vader, Palpatine') - - login_as(create(:user, :level_two, geozone: geozone)) - visit question_path(question) - - expect(page).to have_content('This question is not available on your geozone') - end - - scenario 'Level 2 users who can answer' do - question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') - - login_as(create(:user, :level_two, geozone: geozone)) - visit question_path(question) - - expect(page).to have_link('Answer this question') - end - - scenario 'Level 2 users who have already answered' do - question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') - - user = create(:user, :level_two, geozone: geozone) - create(:poll_answer, question: question, author: user, answer: 'Chewbacca') - - login_as user - visit question_path(question) - - expect(page).to have_link('Answer this question') - end - - scenario 'Level 2 users answering', :js do - question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') - user = create(:user, :level_two, geozone: geozone) - - login_as user - visit question_path(question) - - expect(page).to have_link('Answer this question') - end - - scenario 'Records participation', :js do - question = create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') - user = create(:user, :level_two, geozone: geozone, gender: 'female', date_of_birth: 33.years.ago) - - login_as user - visit question_path(question) - - click_link 'Answer this question' - click_link 'Han Solo' - - expect(page).to_not have_link('Han Solo') - - voter = poll.voters.first - expect(voter.document_number).to eq(user.document_number) - expect(voter.geozone_id).to eq(user.geozone_id) - expect(voter.gender).to eq(user.gender) - expect(voter.age).to eq(33) - expect(voter.poll_id).to eq(poll.id) - end - - end end diff --git a/spec/features/polls/results_spec.rb b/spec/features/polls/results_spec.rb new file mode 100644 index 000000000..326344dd9 --- /dev/null +++ b/spec/features/polls/results_spec.rb @@ -0,0 +1,55 @@ +require 'rails_helper' + +feature 'Poll Results' do + scenario 'List each Poll question', :js do + user1 = create(:user, :level_two) + user2 = create(:user, :level_two) + user3 = create(:user, :level_two) + + poll = create(:poll, results_enabled: true) + question1 = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question1, title: 'Yes') + answer2 = create(:poll_question_answer, question: question1, title: 'No') + + question2 = create(:poll_question, poll: poll) + answer3 = create(:poll_question_answer, question: question2, title: 'Blue') + answer4 = create(:poll_question_answer, question: question2, title: 'Green') + answer5 = create(:poll_question_answer, question: question2, title: 'Yellow') + + login_as user1 + vote_for_poll_via_web(poll, question1, 'Yes') + vote_for_poll_via_web(poll, question2, 'Blue') + expect(Poll::Voter.count).to eq(1) + logout + + login_as user2 + vote_for_poll_via_web(poll, question1, 'Yes') + vote_for_poll_via_web(poll, question2, 'Green') + expect(Poll::Voter.count).to eq(2) + logout + + login_as user3 + vote_for_poll_via_web(poll, question1, 'No') + vote_for_poll_via_web(poll, question2, 'Yellow') + expect(Poll::Voter.count).to eq(3) + logout + + poll.update(ends_at: 1.day.ago) + + visit results_poll_path(poll) + + expect(page).to have_content(question1.title) + expect(page).to have_content(question2.title) + + within("#question_#{question1.id}_results_table") do + expect(find("#answer_#{answer1.id}_result")).to have_content("2 (66.0%)") + expect(find("#answer_#{answer2.id}_result")).to have_content("1 (33.0%)") + end + + within("#question_#{question2.id}_results_table") do + expect(find("#answer_#{answer3.id}_result")).to have_content("1 (33.0%)") + expect(find("#answer_#{answer4.id}_result")).to have_content("1 (33.0%)") + expect(find("#answer_#{answer5.id}_result")).to have_content("1 (33.0%)") + end + end +end diff --git a/spec/features/polls/voter_spec.rb b/spec/features/polls/voter_spec.rb new file mode 100644 index 000000000..aee0ff522 --- /dev/null +++ b/spec/features/polls/voter_spec.rb @@ -0,0 +1,184 @@ +require 'rails_helper' + +feature "Voter" do + + context "Origin" do + + let(:poll) { create(:poll, :current) } + let(:booth) { create(:poll_booth) } + let(:officer) { create(:poll_officer) } + + background do + create(:geozone, :in_census) + create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection) + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment) + end + + scenario "Voting via web - Standard", :js do + poll = create(:poll) + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Yes') + answer2 = create(:poll_question_answer, question: question, title: 'No') + + user = create(:user, :level_two) + + login_as user + visit poll_path(poll) + + within("#poll_question_#{question.id}_answers") do + click_link 'Yes' + expect(page).to_not have_link('Yes') + end + + find(:css, ".js-token-message").should be_visible + token = find(:css, ".js-question-answer")[:href].gsub(/.+?(?=token)/, '').gsub('token=', '') + + expect(page).to have_content "You can write down this vote identifier, to check your vote on the final results: #{token}" + + expect(Poll::Voter.count).to eq(1) + expect(Poll::Voter.first.origin).to eq("web") + end + + scenario "Voting via web as unverified user", :js do + poll = create(:poll) + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Yes') + answer2 = create(:poll_question_answer, question: question, title: 'No') + + user = create(:user, :incomplete_verification) + + login_as user + visit poll_path(poll) + + within("#poll_question_#{question.id}_answers") do + expect(page).to_not have_link('Yes', href: "/questions/#{question.id}/answer?answer=Yes&token=") + expect(page).to_not have_link('No', href: "/questions/#{question.id}/answer?answer=No&token=") + end + + expect(page).to have_content("You must verify your account in order to answer") + expect(page).to_not have_content("You have already participated in this poll. If you vote again it will be overwritten") + end + + scenario "Voting in booth", :js do + user = create(:user, :in_census) + + login_through_form_as_officer(officer.user) + + visit new_officing_residence_path + officing_verify_residence + + expect(page).to have_content poll.name + + within("#poll_#{poll.id}") do + click_button("Confirm vote") + expect(page).to_not have_button("Confirm vote") + expect(page).to have_button('Wait, confirming vote...', disabled: true) + expect(page).to have_content "Vote introduced!" + end + + expect(Poll::Voter.count).to eq(1) + expect(Poll::Voter.first.origin).to eq("booth") + end + + context "Trying to vote the same poll in booth and web" do + + let(:poll) { create(:poll) } + + let(:question) { create(:poll_question, poll: poll) } + let!(:answer1) { create(:poll_question_answer, question: question, title: 'Yes') } + let!(:answer2) { create(:poll_question_answer, question: question, title: 'No') } + + let!(:user) { create(:user, :in_census) } + + scenario "Trying to vote in web and then in booth", :js do + login_as user + vote_for_poll_via_web(poll, question, 'Yes') + expect(Poll::Voter.count).to eq(1) + + click_link "Sign out" + + login_through_form_as_officer(officer.user) + + visit new_officing_residence_path + officing_verify_residence + + expect(page).to have_content poll.name + expect(page).to_not have_button "Confirm vote" + expect(page).to have_content "Has already participated in this poll" + end + + scenario "Trying to vote in booth and then in web", :js do + login_through_form_as_officer(officer.user) + + vote_for_poll_via_booth + + visit root_path + click_link "Sign out" + + login_as user + visit poll_path(poll) + + expect(page).to_not have_link('Yes') + expect(page).to have_content "You have already participated in a physical booth. You can not participate again." + expect(Poll::Voter.count).to eq(1) + end + + scenario "Trying to vote in web again", :js do + login_as user + vote_for_poll_via_web(poll, question, 'Yes') + expect(Poll::Voter.count).to eq(1) + + visit poll_path(poll) + + expect(page).to_not have_selector('.js-token-message') + + expect(page).to have_content "You have already participated in this poll. If you vote again it will be overwritten." + within("#poll_question_#{question.id}_answers") do + expect(page).to_not have_link('Yes') + end + + click_link "Sign out" + + login_as user + visit poll_path(poll) + + within("#poll_question_#{question.id}_answers") do + expect(page).to have_link('Yes') + expect(page).to have_link('No') + end + end + end + + scenario "Voting in poll and then verifiying account", :js do + user = create(:user) + + question = create(:poll_question, poll: poll) + answer1 = create(:poll_question_answer, question: question, title: 'Yes') + answer2 = create(:poll_question_answer, question: question, title: 'No') + + login_through_form_as_officer(officer.user) + vote_for_poll_via_booth + + visit root_path + click_link "Sign out" + + login_as user + visit account_path + click_link 'Verify my account' + + verify_residence + confirm_phone(user) + + visit poll_path(poll) + + expect(page).to_not have_link('Yes') + expect(page).to have_content "You have already participated in a physical booth. You can not participate again." + expect(Poll::Voter.count).to eq(1) + end + + end + +end diff --git a/spec/features/proposal_notifications_spec.rb b/spec/features/proposal_notifications_spec.rb index 4756a1903..1e93f7e13 100644 --- a/spec/features/proposal_notifications_spec.rb +++ b/spec/features/proposal_notifications_spec.rb @@ -189,7 +189,7 @@ feature 'Proposal Notifications' do login_as(user) visit new_proposal_notification_path(proposal_id: proposal.id) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content("You do not have permission to carry out the action") end diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb index d297a294b..28049644b 100644 --- a/spec/features/proposals_spec.rb +++ b/spec/features/proposals_spec.rb @@ -38,13 +38,29 @@ feature 'Proposals' do within("ul.pagination") do expect(page).to have_content("1") - expect(page).to have_content("2") + expect(page).to have_link('2', href: 'http://www.example.com/proposals?page=2') expect(page).to_not have_content("3") click_link "Next", exact: false end expect(page).to have_selector('#proposals .proposal', count: 2) end + + scenario 'Index should show proposal descriptive image only when is defined' do + featured_proposals = create_featured_proposals + proposal = create(:proposal) + proposal_with_image = create(:proposal) + image = create(:image, imageable: proposal_with_image) + + visit proposals_path(proposal) + + within("#proposal_#{proposal.id}") do + expect(page).to have_css("div.no-image") + end + within("#proposal_#{proposal_with_image.id}") do + expect(page).to have_css("img[alt='#{proposal_with_image.image.title}']") + end + end end scenario 'Show' do @@ -540,7 +556,7 @@ feature 'Proposals' do visit edit_proposal_path(proposal) expect(current_path).not_to eq(edit_proposal_path(proposal)) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content 'You do not have permission' end @@ -555,7 +571,7 @@ feature 'Proposals' do visit edit_proposal_path(proposal) expect(current_path).not_to eq(edit_proposal_path(proposal)) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content 'You do not have permission' Setting["max_votes_for_proposal_edit"] = 1000 end @@ -647,6 +663,69 @@ feature 'Proposals' do expect(current_url).to include('order=created_at') expect(current_url).to include('page=1') end + + context 'Recommendations' do + + before do + Setting['feature.user.recommendations'] = true + create(:proposal, title: 'Best', cached_votes_up: 10, tag_list: "Sport") + create(:proposal, title: 'Medium', cached_votes_up: 5, tag_list: "Sport") + create(:proposal, title: 'Worst', cached_votes_up: 1, tag_list: "Sport") + end + + after do + Setting['feature.user.recommendations'] = nil + end + + scenario 'Proposals can not ordered by recommendations when there is not an user logged', :js do + visit proposals_path + + expect(page).not_to have_selector('a', text: 'recommendations') + end + + scenario 'Should display text when there are not recommendeds results', :js do + user = create(:user) + proposal = create(:proposal, tag_list: "Distinct_to_sport") + create(:follow, followable: proposal, user: user) + login_as(user) + visit proposals_path + + click_link 'recommendations' + + expect(page).to have_content "There are not proposals related to your interests" + end + + scenario 'Should display text when user has not related interests', :js do + user = create(:user) + login_as(user) + visit proposals_path + + click_link 'recommendations' + + expect(page).to have_content "Follow proposals so we can give you recommendations" + end + + scenario 'Proposals are ordered by recommendations when there is an user logged', :js do + user = create(:user) + proposal = create(:proposal, tag_list: "Sport") + create(:follow, followable: proposal, user: user) + login_as(user) + + visit proposals_path + + click_link 'recommendations' + + expect(page).to have_selector('a.active', text: 'recommendations') + + within '#proposals-list' do + expect('Best').to appear_before('Medium') + expect('Medium').to appear_before('Worst') + end + + expect(current_url).to include('order=recommendations') + expect(current_url).to include('page=1') + end + end end feature 'Archived proposals' do @@ -1182,6 +1261,32 @@ feature 'Proposals' do end end + scenario "Reorder by recommendations results maintaing search", :js do + Setting['feature.user.recommendations'] = true + user = create(:user) + login_as(user) + proposal1 = create(:proposal, title: "Show you got", cached_votes_up: 10, tag_list: "Sport") + proposal2 = create(:proposal, title: "Show what you got", cached_votes_up: 1, tag_list: "Sport") + proposal3 = create(:proposal, title: "Do not display with same tag", cached_votes_up: 100, tag_list: "Sport") + proposal4 = create(:proposal, title: "Do not display", cached_votes_up: 1) + proposal5 = create(:proposal, tag_list: "Sport") + create(:follow, followable: proposal5, user: user) + + visit proposals_path + fill_in "search", with: "Show you got" + click_button "Search" + click_link 'recommendations' + expect(page).to have_selector("a.active", text: "recommendations") + + within("#proposals") do + expect(all(".proposal")[0].text).to match "Show you got" + expect(all(".proposal")[1].text).to match "Show what you got" + expect(page).to_not have_content "Do not display with same tag" + expect(page).to_not have_content "Do not display" + end + Setting['feature.user.recommendations'] = nil + end + scenario 'After a search do not show featured proposals' do featured_proposals = create_featured_proposals proposal = create(:proposal, title: "Abcdefghi") @@ -1274,17 +1379,17 @@ feature 'Proposals' do it_behaves_like "followable", "proposal", "proposal_path", { "id": "id" } - it_behaves_like "documentable", "proposal", "proposal_path", { "id": "id" } + it_behaves_like "imageable", "proposal", "proposal_path", { "id": "id" } - it_behaves_like "nested documentable", + it_behaves_like "nested imageable", "proposal", "new_proposal_path", { }, - "fill_new_valid_proposal", + "imageable_fill_new_valid_proposal", "Create proposal", "Proposal created successfully" - it_behaves_like "nested documentable", + it_behaves_like "nested imageable", "proposal", "edit_proposal_path", { "id": "id" }, @@ -1292,6 +1397,34 @@ feature 'Proposals' do "Save changes", "Proposal updated successfully" + it_behaves_like "documentable", "proposal", "proposal_path", { "id": "id" } + + it_behaves_like "nested documentable", + "user", + "proposal", + "new_proposal_path", + { }, + "documentable_fill_new_valid_proposal", + "Create proposal", + "Proposal created successfully" + + it_behaves_like "nested documentable", + "user", + "proposal", + "edit_proposal_path", + { "id": "id" }, + nil, + "Save changes", + "Proposal updated successfully" + + it_behaves_like "mappable", + "proposal", + "proposal", + "new_proposal_path", + "edit_proposal_path", + "proposal_path", + { } + scenario 'Erased author' do user = create(:user) proposal = create(:proposal, author: user) @@ -1390,7 +1523,7 @@ feature 'Proposals' do check "proposal_terms_of_service" within('div#js-suggest') do - expect(page).to have_content ("You are seeing 5 of 6 proposals containing the term 'search'") + expect(page).to have_content "You are seeing 5 of 6 proposals containing the term 'search'" end end @@ -1406,7 +1539,7 @@ feature 'Proposals' do check "proposal_terms_of_service" within('div#js-suggest') do - expect(page).to_not have_content ('You are seeing') + expect(page).to_not have_content 'You are seeing' end end end diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index ae2bac6d1..5a73209df 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -314,7 +314,7 @@ feature 'Users' do @user.update(public_interests: true) visit user_path(@user) - expect(page).to have_content("List of interests (Tags of elements this user follows)") + expect(page).to have_content("List of interests (tags of elements this user follows)") end scenario 'Should display custom interests title when user is visiting own user page' do @@ -322,7 +322,7 @@ feature 'Users' do login_as(@user) visit user_path(@user) - expect(page).to have_content("List of interests (Tags of elements you follow)") + expect(page).to have_content("List of interests (tags of elements you follow)") end scenario 'Should display generic empty interests list message when visited user has not interests defined' do diff --git a/spec/features/valuation/budget_investments_spec.rb b/spec/features/valuation/budget_investments_spec.rb index 3f91d8925..a627d9422 100644 --- a/spec/features/valuation/budget_investments_spec.rb +++ b/spec/features/valuation/budget_investments_spec.rb @@ -271,20 +271,20 @@ feature 'Valuation budget investments' do visit valuation_budget_budget_investment_path(@budget, @investment) click_link 'Edit dossier' - expect(find "#budget_investment_feasibility_undecided").to be_checked + expect(find("#budget_investment_feasibility_undecided")).to be_checked choose 'budget_investment_feasibility_feasible' click_button 'Save changes' visit edit_valuation_budget_budget_investment_path(@budget, @investment) - expect(find "#budget_investment_feasibility_undecided").to_not be_checked - expect(find "#budget_investment_feasibility_feasible").to be_checked + expect(find("#budget_investment_feasibility_undecided")).to_not be_checked + expect(find("#budget_investment_feasibility_feasible")).to be_checked choose 'budget_investment_feasibility_undecided' click_button 'Save changes' visit edit_valuation_budget_budget_investment_path(@budget, @investment) - expect(find "#budget_investment_feasibility_undecided").to be_checked + expect(find("#budget_investment_feasibility_undecided")).to be_checked end scenario 'Feasibility selection makes proper fields visible', :js do @@ -295,7 +295,7 @@ feature 'Valuation budget investments' do visit edit_valuation_budget_budget_investment_path(@budget, @investment) - expect(find "#budget_investment_feasibility_undecided").to be_checked + expect(find("#budget_investment_feasibility_undecided")).to be_checked undecided_fields.each do |field| expect(page).to have_content(field) @@ -325,7 +325,7 @@ feature 'Valuation budget investments' do visit edit_valuation_budget_budget_investment_path(@budget, @investment) - expect(find "#budget_investment_feasibility_unfeasible").to be_checked + expect(find("#budget_investment_feasibility_unfeasible")).to be_checked feasible_fields.each do |field| expect(page).to_not have_content(field) end diff --git a/spec/features/valuation_spec.rb b/spec/features/valuation_spec.rb index 5b6cc961c..9e74d9341 100644 --- a/spec/features/valuation_spec.rb +++ b/spec/features/valuation_spec.rb @@ -21,7 +21,7 @@ feature 'Valuation' do visit valuation_root_path expect(current_path).not_to eq(valuation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -34,7 +34,7 @@ feature 'Valuation' do visit valuation_root_path expect(current_path).not_to eq(valuation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -47,7 +47,7 @@ feature 'Valuation' do visit valuation_root_path expect(current_path).not_to eq(valuation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end @@ -60,7 +60,7 @@ feature 'Valuation' do visit valuation_root_path expect(current_path).not_to eq(valuation_root_path) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) expect(page).to have_content "You do not have permission to access this page" end diff --git a/spec/features/welcome_spec.rb b/spec/features/welcome_spec.rb index ce06befcc..245a9923e 100644 --- a/spec/features/welcome_spec.rb +++ b/spec/features/welcome_spec.rb @@ -33,7 +33,7 @@ feature "Welcome screen" do login_through_form_as(user) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) end scenario 'is not shown to organizations' do @@ -41,7 +41,7 @@ feature "Welcome screen" do login_through_form_as(organization.user) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) end scenario 'it is not shown to level-2 users' do @@ -49,7 +49,7 @@ feature "Welcome screen" do login_through_form_as(user) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) end scenario 'it is not shown to level-3 users' do @@ -57,7 +57,7 @@ feature "Welcome screen" do login_through_form_as(user) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) end scenario 'is not shown to administrators' do @@ -65,7 +65,7 @@ feature "Welcome screen" do login_through_form_as(administrator.user) - expect(current_path).to eq(proposals_path) + expect(current_path).to eq(root_path) end end diff --git a/spec/fixtures/files/clippy.gif b/spec/fixtures/files/clippy.gif new file mode 100644 index 000000000..c2c2278af Binary files /dev/null and b/spec/fixtures/files/clippy.gif differ diff --git a/spec/fixtures/files/clippy.jpeg b/spec/fixtures/files/clippy.jpeg new file mode 100644 index 000000000..1edb6659b Binary files /dev/null and b/spec/fixtures/files/clippy.jpeg differ diff --git a/spec/fixtures/files/clippy.jpg b/spec/fixtures/files/clippy.jpg new file mode 100644 index 000000000..1edb6659b Binary files /dev/null and b/spec/fixtures/files/clippy.jpg differ diff --git a/spec/fixtures/files/clippy.png b/spec/fixtures/files/clippy.png new file mode 100644 index 000000000..44e09b4e3 Binary files /dev/null and b/spec/fixtures/files/clippy.png differ diff --git a/spec/fixtures/files/logo_header.gif b/spec/fixtures/files/logo_header.gif new file mode 100644 index 000000000..4bfddd410 Binary files /dev/null and b/spec/fixtures/files/logo_header.gif differ diff --git a/spec/fixtures/files/logo_header.jpg b/spec/fixtures/files/logo_header.jpg new file mode 100644 index 000000000..aeed9e524 Binary files /dev/null and b/spec/fixtures/files/logo_header.jpg differ diff --git a/spec/helpers/comments_helper_spec.rb b/spec/helpers/comments_helper_spec.rb index b1caabe53..040903c96 100644 --- a/spec/helpers/comments_helper_spec.rb +++ b/spec/helpers/comments_helper_spec.rb @@ -14,7 +14,7 @@ RSpec.describe CommentsHelper, type: :helper do describe '#user_level_class' do - def comment_double as_administrator: false, as_moderator: false, official: false + def comment_double(as_administrator: false, as_moderator: false, official: false) user = double official?: official, official_level: 'Y' double as_administrator?: as_administrator, as_moderator?: as_moderator, user: user end diff --git a/spec/helpers/settings_helper_spec.rb b/spec/helpers/settings_helper_spec.rb index 0aa9b8541..0db6fed10 100644 --- a/spec/helpers/settings_helper_spec.rb +++ b/spec/helpers/settings_helper_spec.rb @@ -21,10 +21,10 @@ RSpec.describe SettingsHelper, type: :helper do Setting["feature.f2"] = "" Setting["feature.f3"] = nil - expect(feature? "f1").to eq("active") - expect(feature? "f2").to eq(nil) - expect(feature? "f3").to eq(nil) - expect(feature? "f4").to eq(nil) + expect(feature?("f1")).to eq("active") + expect(feature?("f2")).to eq(nil) + expect(feature?("f3")).to eq(nil) + expect(feature?("f4")).to eq(nil) end end diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb index 55ea8445b..92ba3d6e4 100644 --- a/spec/helpers/users_helper_spec.rb +++ b/spec/helpers/users_helper_spec.rb @@ -17,7 +17,8 @@ describe UsersHelper do debate.hide - expect(comment_commentable_title(comment)).to eq '
+ +