Skip to content

Commit

Permalink
Merge branch 'feature/vouchers-user-promotion' into feature/voucher-r…
Browse files Browse the repository at this point in the history
…edemption
  • Loading branch information
fosterfarrell9 committed Aug 22, 2024
2 parents 8a0e965 + 8e9d0f9 commit b13f875
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 6 deletions.
30 changes: 30 additions & 0 deletions .config/.cypress.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,35 @@ module.exports = {
// Base URL is set via Docker environment variable
viewportHeight: 1000,
viewportWidth: 1400,

// https://docs.cypress.io/api/plugins/browser-launch-api#Changing-browser-preferences
setupNodeEvents(on, _config) {
on("before:browser:launch", (browser, launchOptions) => {
if (browser.family === "chromium" && browser.name !== "electron") {
// auto open devtools
launchOptions.args.push("--auto-open-devtools-for-tabs");

// TODO (clipboard): We use the obsolete clipboard API from browsers, i.e.
// document.execCommand("copy"). There's a new Clipboard API that is supported
// by modern browsers. Once we switch to that API, use the following code
// to allow requesting permission (clipboard permission) in a non-secure
// context (http). Remaining TODO in this case: search for the equivalent
// flag in Firefox & Electron (if we also want to test them).
// launchOptions.args.push("--unsafely-treat-insecure-origin-as-secure=http://mampf:3000");
}

if (browser.family === "firefox") {
// auto open devtools
launchOptions.args.push("-devtools");
}

if (browser.name === "electron") {
// auto open devtools
launchOptions.preferences.devTools = true;
}

return launchOptions;
});
},
},
};
13 changes: 13 additions & 0 deletions .config/commands/docker.justfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ help:
cd {{justfile_directory()}}/docker/development/
docker compose up {{args}}

# Starts the dev docker containers (detached) & shows MaMpf logs
up-logs *args:
#!/usr/bin/env bash
cd {{justfile_directory()}}/docker/development/
docker compose up -d {{args}}
docker compose logs -f mampf

# Shows the log of the specified container
@logs name="mampf":
#!/usr/bin/env bash
cd {{justfile_directory()}}/docker/development/
docker compose logs -f {{name}}

# Starts the dev docker containers and preseeds the database
[confirm("This will reset all your data in the database locally. Continue? (y/n)")]
up-reseed *args:
Expand Down
16 changes: 10 additions & 6 deletions app/models/lecture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -834,12 +834,9 @@ def speakers
User.where(id: SpeakerTalkJoin.where(talk: talks).select(:speaker_id))
end

def older_than?(timespan)
return true unless term

term.begin_date <= Term.active.begin_date - timespan
end

# Determines if the lecture is stale (i.e. older than one year).
# The age of the lecture is determined by the begin date of the term
# in which it was given and the begin date of the current term.
def stale?
older_than?(1.year)
end
Expand Down Expand Up @@ -1051,6 +1048,13 @@ def only_one_lecture
errors.add(:course, :already_present)
end

def older_than?(timespan)
return false unless Term.active
return true unless term

term.begin_date <= Term.active.begin_date - timespan
end

def tutorial_ids_for_tutor(tutor)
TutorTutorialJoin.where(tutor: tutor).select(:tutorial_id)
end
Expand Down
1 change: 1 addition & 0 deletions app/views/lectures/edit/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
id="lecture-nav-content" type="button" role="tab"
href="#content"
data-bs-toggle="pill" data-bs-target="#lecture-pane-content"
data-cy="content-tab-btn"
aria-controls="lecture-pane-content" aria-selected="true">
<%= t('content') %>
</button>
Expand Down
File renamed without changes.
15 changes: 15 additions & 0 deletions spec/cypress/e2e/lectures_spec.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import FactoryBot from "../support/factorybot";

describe("Lecture edit page", () => {
it("shows content tab button", function () {
cy.createUserAndLogin("teacher").then((teacher) => {
FactoryBot.create("lecture", "with_teacher_by_id",
{ teacher_id: teacher.id }).as("lecture");
});

cy.then(() => {
cy.visit(`/lectures/${this.lecture.id}/edit`);
cy.getBySelector("content-tab-btn").should("be.visible");
});
});
});
11 changes: 11 additions & 0 deletions spec/cypress/e2e/vouchers_spec.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,17 @@ describe("If the lecture is not a seminar", () => {
testInvalidateVoucher(role);
});
});

it.skip("copies the voucher hash to the clipboard", function () {
ROLES.filter(role => role !== "speaker").forEach((role) => {
cy.getBySelector(`create-${role}-voucher-btn`).click();
cy.getBySelector(`${role}-voucher-secure-hash`).then(($hash) => {
const hashText = $hash.text();
cy.getBySelector(`copy-${role}-voucher-btn`).click();
cy.assertCopiedToClipboard(hashText);
});
});
});
});
});

Expand Down
51 changes: 51 additions & 0 deletions spec/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,57 @@ Cypress.Commands.add("clickExpectNewTab", { prevSubject: true }, ($subject, args
return cy.wrap($subject).invoke("removeAttr", "target").click(args);
});

Cypress.Commands.add("assertCopiedToClipboard", (_expectedText) => {
cy.fail("Not implemented yet");

// An old method would consist of something like this:
// adapted from https://stackoverflow.com/a/69571115
// and https://stackoverflow.com/a/33928558

//////////////////////////////////////////////////////////////////////////////
// NEW PROPOSED SOLUTION for the new Clipboard API
//////////////////////////////////////////////////////////////////////////////

// TODO (clipboard): We currently use the obsolete clipboard API from browsers,
// i.e. document.execCommand("copy") via the clipboard.js library.
// There's a new Clipboard API that is supported by modern browsers.
// Once we switch to that API, use the following code to test copying to
// the clipboard. Also see this GitHub issue for more information:
// https://github.com/cypress-io/cypress/issues/2752
//
// Note that another option to test the clipboard content then would be
// https://github.com/cypress-io/cypress/issues/2752#issuecomment-1039285381
// which wouldn't even require requesting permissions but might have its
// own limitations.

// Request clipboard permissions
// by https://stackoverflow.com/a/73329952/9655481
// Note that this won't work by default in a non-secure context (http), so we need to
// pass the flag --unsafely-treat-insecure-origin-as-secure=http://mampf:3000
// to the browser when starting it (see the cypress config)
// cy.wrap(Cypress.automation("remote:debugger:protocol", {
// command: "Browser.grantPermissions",
// params: {
// permissions: ["clipboardReadWrite", "clipboardSanitizedWrite"],
// },
// }));

// Make sure clipboard permissions were granted
// https://stackoverflow.com/questions/61650737/how-to-fetch-copied-to-clipboard-content-in-cypress/73329952#comment137190789_69571115
// cy.window().its("navigator.permissions")
// .then(api => api.query({ name: "clipboard-read" }))
// .its("state").should("equal", "granted");

// https://stackoverflow.com/a/75928308/
// cy.window().its("navigator.clipboard")
// .then(clip => clip.readText())
// .should("equal", expectedText);
});

////////////////////////////////////////////////////////////////////////////////
// Custom commands for backend interaction
////////////////////////////////////////////////////////////////////////////////

Cypress.Commands.add("cleanDatabase", () => {
return BackendCaller.callCypressRoute("database_cleaner", "cy.cleanDatabase()", {});
});
Expand Down
8 changes: 8 additions & 0 deletions spec/factories/terms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,13 @@
trait :summer do
season { "SS" }
end

trait :winter do
season { "WS" }
end

trait :active do
active { true }
end
end
end
44 changes: 44 additions & 0 deletions spec/models/lecture_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,50 @@
end
end

describe "#stale?" do
context "when there is no active term" do
it "returns false" do
lecture = FactoryBot.build(:lecture)
expect(lecture.stale?).to be(false)
end
end

context "when there is an active term" do
let(:year) { 2024 }

before(:each) do
FactoryBot.create(:term, :summer, :active, year: year)
end

context "and there is no term associated with the lecture" do
it "returns true" do
lecture = FactoryBot.build(:lecture, :term_independent)
expect(lecture.stale?).to be(true)
end
end

context "and the lecture term begin date is before the active term" \
"begin date minus 1 year" do
let(:lecture_term) { FactoryBot.build(:term, :summer, year: year - 1) }

it "returns true" do
lecture = FactoryBot.build(:lecture, term: lecture_term)
expect(lecture.stale?).to be(true)
end
end

context "when the lecture term begin date is not older than the" \
"active term begin date minus 1 year" do
let(:lecture_term) { FactoryBot.build(:term, :winter, year: year - 1) }

it "returns false" do
lecture = FactoryBot.build(:lecture, term: lecture_term)
expect(lecture.stale?).to be(false)
end
end
end
end

describe "#active_voucher_of_role" do
let(:lecture) { FactoryBot.create(:lecture) }
let(:role) { :tutor }
Expand Down

0 comments on commit b13f875

Please sign in to comment.