diff --git a/.github/workflows/test-convene-journal.yml b/.github/workflows/test-convene-journal.yml new file mode 100644 index 000000000..385725f4c --- /dev/null +++ b/.github/workflows/test-convene-journal.yml @@ -0,0 +1,154 @@ +name: Test Journal +on: push + +env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + # Connect to locally-running Maildev for tests + SMTP_PORT: 1025 + SMTP_DOMAIN: localhost + SMTP_ENABLE_TLS: false + REDIS_HOST: redis + REDIS_PORT: 6379 + HEADLESS: true + +jobs: + setup: + name: Install and cache dependencies + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Update apt + env: + DEBIAN_FRONTEND: noninteractive + run: + sudo apt-get update -qq -o Acquire::Retries=3 + + - name: Install libvips + env: + DEBIAN_FRONTEND: noninteractive + run: + # we only need the library + sudo apt-get install --fix-missing -qq -o Acquire::Retries=3 + libvips + + - name: Setup Ruby and install gems + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Setup Node with cache + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'yarn' + + - name: Install Node dependencies + run: yarn install + + test: + name: Run Tests + runs-on: ubuntu-latest + needs: [setup] + + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + redis: + image: redis + ports: + # Maps port 6379 on service container to the host + - 6379:6379 + # Set health checks to wait until redis has started + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Update apt + env: + DEBIAN_FRONTEND: noninteractive + run: + sudo apt-get update -qq -o Acquire::Retries=3 + + - name: Install libvips + env: + DEBIAN_FRONTEND: noninteractive + run: + # we only need the library + sudo apt-get install --fix-missing -qq -o Acquire::Retries=3 + libvips + + - name: Install Firefox + uses: browser-actions/setup-firefox@latest + + - name: Setup Ruby and install gems + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Setup Node with cache + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'yarn' + + - name: Allow Ruby process to access port 80 + run: sudo setcap 'cap_net_bind_service=+ep' `which ruby` + + - name: Setup CI database.yml + run: cp config/database.yml.github-actions config/database.yml + + - name: Setup rails + run: bin/setup-rails && bin/rails assets:precompile + + - name: Run Tests + env: + HEADLESS: true + run: bundle exec rspec spec/furniture/journal + - name: Upload RSpec Screenshots + uses: actions/upload-artifact@v2 + if: failure() + with: + name: rspec-failed-screenshot + path: tmp/capybara/*.png + + lint: + name: Run style checks + runs-on: ubuntu-latest + needs: [setup] + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Ruby and install gems + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Setup Node with cache + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'yarn' + + - name: Install Node dependencies + run: yarn install + + - run: bundle exec rubocop --parallel --config .rubocop.yml + - run: yarn prettier --check "./**/*.{scss,css,js}" diff --git a/app/furniture/journal/entries/_form.html.erb b/app/furniture/journal/entries/_form.html.erb index 42186983f..8f5d33d03 100644 --- a/app/furniture/journal/entries/_form.html.erb +++ b/app/furniture/journal/entries/_form.html.erb @@ -1,5 +1,7 @@ <%= form_with model: entry.location, class: "flex flex-col grow" do |f| %> <%= render "text_field", { attribute: :headline, form: f} %> + <%= render "text_area", { attribute: :summary, form: f} %> + <%= render "text_area", { attribute: :body, form: f, field_classes: "grow", container_classes: "grow flex flex-col"} %> <%= render "datetime_field", { attribute: :published_at, form: f} %> diff --git a/app/furniture/journal/entry.rb b/app/furniture/journal/entry.rb index dd48dd6cd..e5aed1e5a 100644 --- a/app/furniture/journal/entry.rb +++ b/app/furniture/journal/entry.rb @@ -33,6 +33,9 @@ class Entry < ApplicationRecord scope :matching_keywords, ->(keywords) { where("keywords::text[] && ARRAY[?]::text[]", keywords) } + SUMMARY_MAX_LENGTH = 300 + validates :summary, length: {maximum: SUMMARY_MAX_LENGTH, allow_blank: true} + def migrate_to(journal:, keywords: []) new_body = keywords.present? ? body + "\n##{keywords.join(" #")}" : body update(journal: journal, body: new_body) diff --git a/app/furniture/journal/entry_policy.rb b/app/furniture/journal/entry_policy.rb index f54d4fb65..ebbb6bbe1 100644 --- a/app/furniture/journal/entry_policy.rb +++ b/app/furniture/journal/entry_policy.rb @@ -17,7 +17,7 @@ def update? end def permitted_attributes(_params) - %i[headline body published_at] + %i[headline summary body published_at] end class Scope < ApplicationScope diff --git a/db/migrate/20240129014151_journal_add_description_to_entry.rb b/db/migrate/20240129014151_journal_add_description_to_entry.rb new file mode 100644 index 000000000..03ef6878c --- /dev/null +++ b/db/migrate/20240129014151_journal_add_description_to_entry.rb @@ -0,0 +1,5 @@ +class JournalAddDescriptionToEntry < ActiveRecord::Migration[7.1] + def change + add_column :journal_entries, :summary, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index 442d9a280..e0d2ce6e7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -116,6 +116,7 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "keywords", array: true + t.text "summary" t.index ["journal_id"], name: "index_journal_entries_on_journal_id" end diff --git a/spec/furniture/journal/entry_spec.rb b/spec/furniture/journal/entry_spec.rb index 8d16fff4d..840bbeb76 100644 --- a/spec/furniture/journal/entry_spec.rb +++ b/spec/furniture/journal/entry_spec.rb @@ -22,6 +22,10 @@ end end + describe "#summary" do + it { is_expected.to validate_length_of(:summary).is_at_most(300).allow_blank } + end + describe "#save" do let(:entry) { create(:journal_entry, body: "#GoodTimes") } let(:journal) { entry.journal } diff --git a/spec/furniture/journal/writing_entries_system_spec.rb b/spec/furniture/journal/writing_entries_system_spec.rb new file mode 100644 index 000000000..bd4be88d4 --- /dev/null +++ b/spec/furniture/journal/writing_entries_system_spec.rb @@ -0,0 +1,30 @@ +require "rails_helper" + +# @see https://github.com/zinc-collective/convene-journal/issues/2 +RSpec.describe "Writing Entries", type: :system do + let(:space) { create(:space, :with_entrance, :with_members) } + let(:journal) { create(:journal, room: space.entrance) } + + before do + sign_in(space.members.first, space) + end + + it "saves the headline, summary and body" do # rubocop:disable RSpec/ExampleLength + visit(polymorphic_path(journal.location(:new, child: :entry))) + + body = 1000.times.map { Faker::Books::Dune.quote }.join("\n\n") + fill_in("Headline", with: "1000 Dune Quotes") + fill_in("Body", with: body) + summary = %( + So you thought you wanted 1000 Dune Quotes? + Well, you were wrong. But here they are anyway! + ) + fill_in("Summary", with: summary) + + click_button("Create") + entry = journal.entries.last + expect(entry.headline).to eq("1000 Dune Quotes") + expect(entry.body).to eq(body) + expect(entry.summary).to eq(summary) + end +end