From 2855caf98e687f3c96cfd293d6cf82dc04548cd5 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Tue, 24 Mar 2020 18:41:14 -0400
Subject: [PATCH 01/18] add SaveMessage component to Header
---
web/src/components/Header.js | 4 +-
web/src/components/SaveMessage.js | 71 +++++++++++++++
web/src/components/SaveMessage.test.js | 115 +++++++++++++++++++++++++
3 files changed, 189 insertions(+), 1 deletion(-)
create mode 100644 web/src/components/SaveMessage.js
create mode 100644 web/src/components/SaveMessage.test.js
diff --git a/web/src/components/Header.js b/web/src/components/Header.js
index 6f1a60450b..939292fa8e 100644
--- a/web/src/components/Header.js
+++ b/web/src/components/Header.js
@@ -8,6 +8,7 @@ import { getIsAdmin } from '../reducers/user.selector';
import { t } from '../i18n';
import DashboardButton from './DashboardButton';
+import SaveMessage from './SaveMessage';
import Icon, {
Check,
@@ -86,7 +87,8 @@ class Header extends Component {
) : (
- Saved {lastSaved}
+
+
)}
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
new file mode 100644
index 0000000000..01a8ce3742
--- /dev/null
+++ b/web/src/components/SaveMessage.js
@@ -0,0 +1,71 @@
+import React from "react";
+import moment from "moment";
+
+// Configure moment to display '1 time-unit ago' instead of 'a time-unit ago'
+// https://github.com/moment/moment/issues/3764
+moment.updateLocale("en", {
+ relativeTime: {
+ s: "seconds",
+ m: "1 minute",
+ mm: "%d minutes",
+ h: "1 hour",
+ hh: "%d hours",
+ d: "1 day",
+ dd: "%d days",
+ M: "1 month",
+ MM: "%d months",
+ y: "1 year",
+ yy: "%d years",
+ },
+});
+
+class SaveMessage extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ currentMoment: moment(),
+ };
+ }
+
+ componentDidMount() {
+ this.timerID = setInterval(() => this.updateClock(), 1000);
+ }
+
+ componentWillUnmount() {
+ clearInterval(this.timerID);
+ }
+
+ updateClock() {
+ this.setState({
+ currentMoment: moment(),
+ });
+ }
+
+ render() {
+ const { lastSaved } = this.props;
+ const { currentMoment } = this.state;
+
+ const lastSavedMoment = moment(lastSaved);
+ const minutesOld = currentMoment.diff(lastSavedMoment, "minutes");
+ const minutesPerDay = 60 * 24;
+ const minutesPerYear = minutesPerDay * 365.25;
+ let result = "Last saved";
+
+ if (minutesOld < 1) return "Saved";
+ if (1 <= minutesOld && minutesOld < minutesPerDay) {
+ // https://momentjs.com/docs/#/displaying/format/
+ result = `${result} ${lastSavedMoment.format("hh:mm a")}`;
+ }
+ if (minutesPerDay <= minutesOld && minutesOld < minutesPerYear) {
+ result = `${result} ${lastSavedMoment.format("MMMM D")}`;
+ }
+ if (minutesPerYear <= minutesOld) {
+ result = `${result} ${lastSavedMoment.format("MMMM D, YYYY")}`;
+ }
+ result = `${result} (${lastSavedMoment.fromNow()})`;
+ return result;
+ }
+}
+
+export default SaveMessage;
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
new file mode 100644
index 0000000000..7abb958825
--- /dev/null
+++ b/web/src/components/SaveMessage.test.js
@@ -0,0 +1,115 @@
+import React from "react";
+import { shallow } from "enzyme";
+import moment from "moment";
+import SaveMessage from "./SaveMessage";
+
+describe("", () => {
+ let lastSaved, subject;
+
+ describe('when saved less than 1 minute ago, it displays "Saved"', () => {
+ [
+ ["1 second ago", 1],
+ ["2 seconds ago", 2],
+ ["30 seconds ago", 30],
+ ["59 seconds", 59],
+ ].forEach(([testName, seconds]) => {
+ test(testName, () => {
+ lastSaved = moment().subtract(seconds, "seconds");
+ subject = shallow(
+
+ );
+ expect(subject.text()).toEqual("Saved");
+ });
+ });
+ });
+
+ describe("given current time is January 1, 2020 12:00 pm", () => {
+ let jan1AtNoon = new Date(2020, 0, 1, 12, 0);
+ let mockDateNow;
+
+ beforeEach(() => {
+ mockDateNow = jest
+ .spyOn(Date, "now")
+ .mockReturnValue(jan1AtNoon.getTime());
+ });
+
+ afterEach(() => {
+ mockDateNow.mockRestore();
+ });
+
+ describe("when saved 1 minute ago", () => {
+ it('displays "Last saved 11:59 am (1 minute ago)"', () => {
+ lastSaved = moment(jan1AtNoon).subtract(1, "minutes");
+ subject = shallow(
+
+ );
+ expect(subject.text().startsWith("Last saved")).toEqual(true);
+ expect(subject.text().includes("11:59 am")).toEqual(true);
+ expect(subject.text().endsWith("(1 minute ago)")).toEqual(true);
+ });
+ });
+
+ describe("when saved 23 hours and 59 minutes ago", () => {
+ it('displays "Last saved 12:01 pm (1 day ago)"', () => {
+ lastSaved = moment(jan1AtNoon)
+ .subtract(23, "hours")
+ .subtract(59, "minutes");
+ subject = shallow(
+
+ );
+ expect(subject.text().startsWith("Last saved")).toEqual(true);
+ expect(subject.text().includes("12:01 pm")).toEqual(true);
+ expect(subject.text().endsWith("(1 day ago)")).toEqual(true);
+ });
+ });
+
+ describe("when saved 24 hours ago", () => {
+ it('displays "Last saved December 30 (1 day ago)"', () => {
+ lastSaved = moment().subtract(1, "day");
+ subject = shallow(
+
+ );
+ expect(subject.text().startsWith("Last saved")).toEqual(true);
+ expect(subject.text().includes("December 31")).toEqual(true);
+ expect(subject.text().endsWith("(1 day ago)")).toEqual(true);
+ });
+ });
+
+ describe("when saved 30 days ago", () => {
+ it('displays "Last saved December 30 (1 month ago)"', () => {
+ lastSaved = moment().subtract(30, "day");
+ subject = shallow(
+
+ );
+ expect(subject.text().startsWith("Last saved")).toEqual(true);
+ expect(subject.text().includes("December 2")).toEqual(true);
+ expect(subject.text().endsWith("(1 month ago)")).toEqual(true);
+ });
+ });
+
+ describe("when saved 354 days ago", () => {
+ it('displays "Last saved January 2 (1 year ago)"', () => {
+ lastSaved = moment().subtract(364, "day");
+ subject = shallow(
+
+ );
+ expect(subject.text().startsWith("Last saved")).toEqual(true);
+ expect(subject.text().includes("January 2")).toEqual(true);
+ expect(subject.text().includes("2019")).toEqual(false);
+ expect(subject.text().endsWith("(1 year ago)")).toEqual(true);
+ });
+ });
+
+ describe("when saved 3 years ago", () => {
+ it('displays "Last saved January 1, 2017 (3 years ago)"', () => {
+ lastSaved = moment().subtract(3, "years");
+ subject = shallow(
+
+ );
+ expect(subject.text().startsWith("Last saved")).toEqual(true);
+ expect(subject.text().includes("January 1, 2017")).toEqual(true);
+ expect(subject.text().endsWith("(3 years ago)")).toEqual(true);
+ });
+ });
+ });
+});
From f9071f0bc077af9674f26156b21fd47c1954ac63 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Wed, 25 Mar 2020 10:47:53 -0400
Subject: [PATCH 02/18] preserve space between Check and SaveMessage components
---
web/src/components/Header.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/web/src/components/Header.js b/web/src/components/Header.js
index 939292fa8e..3f8faebe58 100644
--- a/web/src/components/Header.js
+++ b/web/src/components/Header.js
@@ -87,8 +87,7 @@ class Header extends Component {
) : (
-
-
+
)}
From 53f3b9b721687c41d1ea59aa660c00622b290344 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Wed, 25 Mar 2020 12:13:38 -0400
Subject: [PATCH 03/18] use moment#duration to calculate time differences, use
expect#toMatch for better errors
---
web/src/components/SaveMessage.js | 15 +++++----
web/src/components/SaveMessage.test.js | 45 +++++++++++++-------------
2 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
index 01a8ce3742..620d1c8470 100644
--- a/web/src/components/SaveMessage.js
+++ b/web/src/components/SaveMessage.js
@@ -47,23 +47,24 @@ class SaveMessage extends React.Component {
const { currentMoment } = this.state;
const lastSavedMoment = moment(lastSaved);
- const minutesOld = currentMoment.diff(lastSavedMoment, "minutes");
- const minutesPerDay = 60 * 24;
- const minutesPerYear = minutesPerDay * 365.25;
+ const difference = currentMoment.diff(lastSavedMoment);
+ const duration = moment.duration(difference);
let result = "Last saved";
- if (minutesOld < 1) return "Saved";
- if (1 <= minutesOld && minutesOld < minutesPerDay) {
+ if (duration.asMinutes() < 1) return "Saved";
+
+ if (1 <= duration.asMinutes() && duration.asDays() < 1) {
// https://momentjs.com/docs/#/displaying/format/
result = `${result} ${lastSavedMoment.format("hh:mm a")}`;
}
- if (minutesPerDay <= minutesOld && minutesOld < minutesPerYear) {
+ if (1 <= duration.asDays() && duration.asYears() < 1) {
result = `${result} ${lastSavedMoment.format("MMMM D")}`;
}
- if (minutesPerYear <= minutesOld) {
+ if (1 <= duration.asYears()) {
result = `${result} ${lastSavedMoment.format("MMMM D, YYYY")}`;
}
result = `${result} (${lastSavedMoment.fromNow()})`;
+
return result;
}
}
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index 7abb958825..633495c0bd 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -43,9 +43,9 @@ describe("", () => {
subject = shallow(
);
- expect(subject.text().startsWith("Last saved")).toEqual(true);
- expect(subject.text().includes("11:59 am")).toEqual(true);
- expect(subject.text().endsWith("(1 minute ago)")).toEqual(true);
+ expect(subject.text()).toMatch(/^Last saved/);
+ expect(subject.text()).toMatch(/11:59 am/);
+ expect(subject.text()).toMatch(/\(1 minute ago\)$/);
});
});
@@ -57,46 +57,47 @@ describe("", () => {
subject = shallow(
);
- expect(subject.text().startsWith("Last saved")).toEqual(true);
- expect(subject.text().includes("12:01 pm")).toEqual(true);
- expect(subject.text().endsWith("(1 day ago)")).toEqual(true);
+ expect(subject.text()).toMatch(/^Last saved/);
+ expect(subject.text()).toMatch(/12:01 pm/);
+ expect(subject.text()).toMatch(/\(1 day ago\)$/);
});
});
- describe("when saved 24 hours ago", () => {
+ describe("when saved 1 day ago", () => {
it('displays "Last saved December 30 (1 day ago)"', () => {
lastSaved = moment().subtract(1, "day");
subject = shallow(
);
- expect(subject.text().startsWith("Last saved")).toEqual(true);
- expect(subject.text().includes("December 31")).toEqual(true);
- expect(subject.text().endsWith("(1 day ago)")).toEqual(true);
+ expect(subject.text()).toMatch(/^Last saved/);
+ expect(subject.text()).toMatch(/December 31/);
+ expect(subject.text()).toMatch(/\(1 day ago\)$/);
});
});
describe("when saved 30 days ago", () => {
- it('displays "Last saved December 30 (1 month ago)"', () => {
+ it('displays "Last saved December 2 (1 month ago)"', () => {
lastSaved = moment().subtract(30, "day");
subject = shallow(
);
- expect(subject.text().startsWith("Last saved")).toEqual(true);
- expect(subject.text().includes("December 2")).toEqual(true);
- expect(subject.text().endsWith("(1 month ago)")).toEqual(true);
+ expect(subject.text()).toMatch(/^Last saved/);
+ expect(subject.text()).toMatch(/December 2/);
+ expect(subject.text()).not.toMatch(/2019/);
+ expect(subject.text()).toMatch(/\(1 month ago\)$/);
});
});
- describe("when saved 354 days ago", () => {
+ describe("when saved 364 days ago", () => {
it('displays "Last saved January 2 (1 year ago)"', () => {
lastSaved = moment().subtract(364, "day");
subject = shallow(
);
- expect(subject.text().startsWith("Last saved")).toEqual(true);
- expect(subject.text().includes("January 2")).toEqual(true);
- expect(subject.text().includes("2019")).toEqual(false);
- expect(subject.text().endsWith("(1 year ago)")).toEqual(true);
+ expect(subject.text()).toMatch(/^Last saved/);
+ expect(subject.text()).toMatch(/January 2/);
+ expect(subject.text()).not.toMatch(/2019/);
+ expect(subject.text()).toMatch(/\(1 year ago\)$/);
});
});
@@ -106,9 +107,9 @@ describe("", () => {
subject = shallow(
);
- expect(subject.text().startsWith("Last saved")).toEqual(true);
- expect(subject.text().includes("January 1, 2017")).toEqual(true);
- expect(subject.text().endsWith("(3 years ago)")).toEqual(true);
+ expect(subject.text()).toMatch(/^Last saved/);
+ expect(subject.text()).toMatch(/January 1, 2017/);
+ expect(subject.text()).toMatch(/\(3 years ago\)$/);
});
});
});
From 66aab17e43cd1924584845fb541ebbaef13a81ee Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Wed, 25 Mar 2020 17:55:42 -0400
Subject: [PATCH 04/18] appease the demands of our linter
---
web/src/components/SaveMessage.js | 25 ++++++++++++++++++++-----
web/src/components/SaveMessage.test.js | 5 +++--
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
index 620d1c8470..592cfca627 100644
--- a/web/src/components/SaveMessage.js
+++ b/web/src/components/SaveMessage.js
@@ -1,5 +1,6 @@
-import React from "react";
import moment from "moment";
+import React from "react";
+import PropTypes from 'prop-types';
// Configure moment to display '1 time-unit ago' instead of 'a time-unit ago'
// https://github.com/moment/moment/issues/3764
@@ -53,14 +54,16 @@ class SaveMessage extends React.Component {
if (duration.asMinutes() < 1) return "Saved";
- if (1 <= duration.asMinutes() && duration.asDays() < 1) {
- // https://momentjs.com/docs/#/displaying/format/
+ // eslint's "yoda": "Expected literal to be on the right side of <="
+ // Which is easier to visualize on a number line, Mr. Yoda?
+ // lowerBound <= object.value() && object.value() < upperBound // or...
+ if (duration.asMinutes() <= 1 && duration.asDays() < 1) {
result = `${result} ${lastSavedMoment.format("hh:mm a")}`;
}
- if (1 <= duration.asDays() && duration.asYears() < 1) {
+ if (duration.asDays() <= 1 && duration.asYears() < 1) {
result = `${result} ${lastSavedMoment.format("MMMM D")}`;
}
- if (1 <= duration.asYears()) {
+ if (duration.asYears() <= 1) {
result = `${result} ${lastSavedMoment.format("MMMM D, YYYY")}`;
}
result = `${result} (${lastSavedMoment.fromNow()})`;
@@ -69,4 +72,16 @@ class SaveMessage extends React.Component {
}
}
+SaveMessage.propTypes = {
+ lastSaved: PropTypes.oneOfType([
+ PropTypes.instanceOf(Date),
+ PropTypes.instanceOf(moment),
+ PropTypes.string
+ ].isRequred),
+};
+
+SaveMessage.defaultProps = {
+ lastSaved: moment(),
+};
+
export default SaveMessage;
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index 633495c0bd..7f43f2d8fa 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -4,7 +4,8 @@ import moment from "moment";
import SaveMessage from "./SaveMessage";
describe("", () => {
- let lastSaved, subject;
+ let lastSaved;
+ let subject;
describe('when saved less than 1 minute ago, it displays "Saved"', () => {
[
@@ -24,7 +25,7 @@ describe("", () => {
});
describe("given current time is January 1, 2020 12:00 pm", () => {
- let jan1AtNoon = new Date(2020, 0, 1, 12, 0);
+ const jan1AtNoon = new Date(2020, 0, 1, 12, 0);
let mockDateNow;
beforeEach(() => {
From d8adad13c947ea498026bf3d6e8a85af9857a295 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Wed, 25 Mar 2020 18:12:31 -0400
Subject: [PATCH 05/18] thanks, yoda...
---
web/src/components/SaveMessage.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
index 592cfca627..6bd919571e 100644
--- a/web/src/components/SaveMessage.js
+++ b/web/src/components/SaveMessage.js
@@ -57,13 +57,13 @@ class SaveMessage extends React.Component {
// eslint's "yoda": "Expected literal to be on the right side of <="
// Which is easier to visualize on a number line, Mr. Yoda?
// lowerBound <= object.value() && object.value() < upperBound // or...
- if (duration.asMinutes() <= 1 && duration.asDays() < 1) {
+ if (duration.asMinutes() >= 1 && duration.asDays() < 1) {
result = `${result} ${lastSavedMoment.format("hh:mm a")}`;
}
- if (duration.asDays() <= 1 && duration.asYears() < 1) {
+ if (duration.asDays() >= 1 && duration.asYears() < 1) {
result = `${result} ${lastSavedMoment.format("MMMM D")}`;
}
- if (duration.asYears() <= 1) {
+ if (duration.asYears() >= 1) {
result = `${result} ${lastSavedMoment.format("MMMM D, YYYY")}`;
}
result = `${result} (${lastSavedMoment.fromNow()})`;
From 8f932be310930b063d296e9dc5af81a3a1c89678 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Wed, 25 Mar 2020 18:13:09 -0400
Subject: [PATCH 06/18] update Header test and snapshot
---
web/src/components/Header.test.js | 4 ++--
web/src/components/__snapshots__/Header.test.js.snap | 6 ++++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/web/src/components/Header.test.js b/web/src/components/Header.test.js
index 782897b25c..b2a80e39ad 100644
--- a/web/src/components/Header.test.js
+++ b/web/src/components/Header.test.js
@@ -139,7 +139,7 @@ describe('Header component', () => {
}}
isAdmin={false}
isSaving={false}
- lastSaved="last save date"
+ lastSaved="2020-01-01T12:00:00.000Z"
pushRoute={() => {}}
showSiteTitle={false}
/>
@@ -159,7 +159,7 @@ describe('Header component', () => {
}}
isAdmin={false}
isSaving
- lastSaved="last save date"
+ lastSaved="2020-01-01T17:00:00.000Z"
pushRoute={() => {}}
showSiteTitle={false}
/>
diff --git a/web/src/components/__snapshots__/Header.test.js.snap b/web/src/components/__snapshots__/Header.test.js.snap
index 150254ea37..f77b8b5bb0 100644
--- a/web/src/components/__snapshots__/Header.test.js.snap
+++ b/web/src/components/__snapshots__/Header.test.js.snap
@@ -605,8 +605,10 @@ exports[`Header component renders the state user home title when a state user is
- Saved
- last save date
+
+
From 063f850034b3ab5b8823d0a75a69ff39d90f8377 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Thu, 26 Mar 2020 11:23:41 -0400
Subject: [PATCH 07/18] working auto-update test
---
web/src/components/SaveMessage.test.js | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index 7f43f2d8fa..e58ffe3ff8 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -24,6 +24,25 @@ describe("", () => {
});
});
+ describe("when observed saved time changes from 59.500s to 1m", () => {
+ it('auto-updates', (done) => {
+ lastSaved = moment().subtract(59500, "milliseconds");
+ subject = shallow(
+
+ );
+ expect(subject.text()).toMatch("Saved");
+
+ setTimeout(() => {
+ try {
+ expect(subject.text()).toMatch(/\(1 minute ago\)$/);
+ done();
+ } catch (e) {
+ done.fail(e);
+ }
+ }, 1000);
+ })
+ })
+
describe("given current time is January 1, 2020 12:00 pm", () => {
const jan1AtNoon = new Date(2020, 0, 1, 12, 0);
let mockDateNow;
From 69e65a87b62a143d3c245b69beda68f7bda7d6de Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Thu, 26 Mar 2020 11:26:10 -0400
Subject: [PATCH 08/18] add dem semicolons
---
web/src/components/SaveMessage.test.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index e58ffe3ff8..012ba90201 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -40,8 +40,8 @@ describe("", () => {
done.fail(e);
}
}, 1000);
- })
- })
+ });
+ });
describe("given current time is January 1, 2020 12:00 pm", () => {
const jan1AtNoon = new Date(2020, 0, 1, 12, 0);
From 99421c4fd85106fb0b5b1bc026ce603e498e6fa0 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Thu, 26 Mar 2020 11:42:48 -0400
Subject: [PATCH 09/18] ugly auto-update test, but it seems to work
---
web/src/components/SaveMessage.test.js | 35 ++++++++++++++++----------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index 012ba90201..365d1dbcba 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -24,22 +24,31 @@ describe("", () => {
});
});
- describe("when observed saved time changes from 59.500s to 1m", () => {
- it('auto-updates', (done) => {
- lastSaved = moment().subtract(59500, "milliseconds");
+ describe("when observed saved time changes to 1 minute ago", () => {
+ const now = new Date(2020, 0, 1, 12, 0);
+ const oneMinuteFromNow = new Date(2020, 0, 1, 12, 1);
+ let mockDateNow;
+
+ beforeEach(() => {
+ jest.useFakeTimers();
+ mockDateNow = jest
+ .spyOn(Date, "now")
+ .mockReturnValueOnce(now)
+ .mockReturnValue(oneMinuteFromNow);
+ });
+
+ afterEach(() => {
+ mockDateNow.mockRestore();
+ jest.clearAllTimers();
+ });
+
+ it('auto-updates', () => {
subject = shallow(
-
+
);
expect(subject.text()).toMatch("Saved");
-
- setTimeout(() => {
- try {
- expect(subject.text()).toMatch(/\(1 minute ago\)$/);
- done();
- } catch (e) {
- done.fail(e);
- }
- }, 1000);
+ jest.advanceTimersByTime(1000);
+ expect(subject.text()).toMatch(/\(1 minute ago\)$/);
});
});
From ce556c75ef8a506aa1bff10f6acc17011561bcd3 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Thu, 26 Mar 2020 14:51:47 -0400
Subject: [PATCH 10/18] refactor tests
---
web/src/components/SaveMessage.test.js | 84 ++++----------------------
1 file changed, 13 insertions(+), 71 deletions(-)
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index 365d1dbcba..5232450d42 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -42,7 +42,7 @@ describe("", () => {
jest.clearAllTimers();
});
- it('auto-updates', () => {
+ it('auto-updates from "Saved" to (1 minute ago)', () => {
subject = shallow(
);
@@ -66,79 +66,21 @@ describe("", () => {
mockDateNow.mockRestore();
});
- describe("when saved 1 minute ago", () => {
- it('displays "Last saved 11:59 am (1 minute ago)"', () => {
- lastSaved = moment(jan1AtNoon).subtract(1, "minutes");
- subject = shallow(
-
- );
- expect(subject.text()).toMatch(/^Last saved/);
- expect(subject.text()).toMatch(/11:59 am/);
- expect(subject.text()).toMatch(/\(1 minute ago\)$/);
- });
- });
-
- describe("when saved 23 hours and 59 minutes ago", () => {
- it('displays "Last saved 12:01 pm (1 day ago)"', () => {
- lastSaved = moment(jan1AtNoon)
- .subtract(23, "hours")
- .subtract(59, "minutes");
- subject = shallow(
-
- );
- expect(subject.text()).toMatch(/^Last saved/);
- expect(subject.text()).toMatch(/12:01 pm/);
- expect(subject.text()).toMatch(/\(1 day ago\)$/);
- });
- });
-
- describe("when saved 1 day ago", () => {
- it('displays "Last saved December 30 (1 day ago)"', () => {
- lastSaved = moment().subtract(1, "day");
- subject = shallow(
-
- );
- expect(subject.text()).toMatch(/^Last saved/);
- expect(subject.text()).toMatch(/December 31/);
- expect(subject.text()).toMatch(/\(1 day ago\)$/);
- });
- });
-
- describe("when saved 30 days ago", () => {
- it('displays "Last saved December 2 (1 month ago)"', () => {
- lastSaved = moment().subtract(30, "day");
- subject = shallow(
-
- );
- expect(subject.text()).toMatch(/^Last saved/);
- expect(subject.text()).toMatch(/December 2/);
- expect(subject.text()).not.toMatch(/2019/);
- expect(subject.text()).toMatch(/\(1 month ago\)$/);
- });
- });
-
- describe("when saved 364 days ago", () => {
- it('displays "Last saved January 2 (1 year ago)"', () => {
- lastSaved = moment().subtract(364, "day");
- subject = shallow(
-
- );
- expect(subject.text()).toMatch(/^Last saved/);
- expect(subject.text()).toMatch(/January 2/);
- expect(subject.text()).not.toMatch(/2019/);
- expect(subject.text()).toMatch(/\(1 year ago\)$/);
- });
- });
-
- describe("when saved 3 years ago", () => {
- it('displays "Last saved January 1, 2017 (3 years ago)"', () => {
- lastSaved = moment().subtract(3, "years");
+ [
+ [1, "minute", "Last saved 11:59 am (1 minute ago)"],
+ [60 * 24 - 1, "minutes", "Last saved 12:01 pm (1 day ago)"],
+ [1, "day", "Last saved December 31 (1 day ago)"],
+ [30, "days", "Last saved December 2 (1 month ago)"],
+ [364, "days", "Last saved January 2 (1 year ago)"],
+ [3, "years", "Last saved January 1, 2017 (3 years ago)"],
+ ].forEach(([value, timeUnit, result]) => {
+ let testName = `when saved ${value} ${timeUnit} ago, it displays "${result}"`
+ test(testName, () => {
+ lastSaved = moment().subtract(value, timeUnit);
subject = shallow(
);
- expect(subject.text()).toMatch(/^Last saved/);
- expect(subject.text()).toMatch(/January 1, 2017/);
- expect(subject.text()).toMatch(/\(3 years ago\)$/);
+ expect(subject.text()).toEqual(result);
});
});
});
From 4356bbdbb0405a6be30e93b773795371ec8ae2f9 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Thu, 26 Mar 2020 16:47:02 -0400
Subject: [PATCH 11/18] remove leading zero from hour
---
web/src/components/SaveMessage.js | 2 +-
web/src/components/SaveMessage.test.js | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
index 6bd919571e..d5ce35e918 100644
--- a/web/src/components/SaveMessage.js
+++ b/web/src/components/SaveMessage.js
@@ -58,7 +58,7 @@ class SaveMessage extends React.Component {
// Which is easier to visualize on a number line, Mr. Yoda?
// lowerBound <= object.value() && object.value() < upperBound // or...
if (duration.asMinutes() >= 1 && duration.asDays() < 1) {
- result = `${result} ${lastSavedMoment.format("hh:mm a")}`;
+ result = `${result} ${lastSavedMoment.format("h:mm a")}`;
}
if (duration.asDays() >= 1 && duration.asYears() < 1) {
result = `${result} ${lastSavedMoment.format("MMMM D")}`;
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index 5232450d42..ff00835ed3 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -69,12 +69,13 @@ describe("", () => {
[
[1, "minute", "Last saved 11:59 am (1 minute ago)"],
[60 * 24 - 1, "minutes", "Last saved 12:01 pm (1 day ago)"],
+ [3, "hours", "Last saved 9:00 am (3 hours ago)"],
[1, "day", "Last saved December 31 (1 day ago)"],
[30, "days", "Last saved December 2 (1 month ago)"],
[364, "days", "Last saved January 2 (1 year ago)"],
[3, "years", "Last saved January 1, 2017 (3 years ago)"],
].forEach(([value, timeUnit, result]) => {
- let testName = `when saved ${value} ${timeUnit} ago, it displays "${result}"`
+ const testName = `when saved ${value} ${timeUnit} ago, it displays "${result}"`
test(testName, () => {
lastSaved = moment().subtract(value, timeUnit);
subject = shallow(
From 022adc8587f28cb5e0603018c5b41b5f82ee2dd1 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Fri, 27 Mar 2020 10:10:06 -0400
Subject: [PATCH 12/18] address feedback
---
web/src/components/SaveMessage.js | 29 +++++++++++---------------
web/src/components/SaveMessage.test.js | 16 ++++++--------
2 files changed, 18 insertions(+), 27 deletions(-)
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
index d5ce35e918..f5cc9d5155 100644
--- a/web/src/components/SaveMessage.js
+++ b/web/src/components/SaveMessage.js
@@ -50,24 +50,19 @@ class SaveMessage extends React.Component {
const lastSavedMoment = moment(lastSaved);
const difference = currentMoment.diff(lastSavedMoment);
const duration = moment.duration(difference);
- let result = "Last saved";
+ let result = "Last saved ";
if (duration.asMinutes() < 1) return "Saved";
- // eslint's "yoda": "Expected literal to be on the right side of <="
- // Which is easier to visualize on a number line, Mr. Yoda?
- // lowerBound <= object.value() && object.value() < upperBound // or...
- if (duration.asMinutes() >= 1 && duration.asDays() < 1) {
- result = `${result} ${lastSavedMoment.format("h:mm a")}`;
+ if (duration.asDays() < 1) {
+ result += lastSavedMoment.format("h:mm a");
+ } else if (duration.asYears() < 1) {
+ result += lastSavedMoment.format("MMMM D");
+ } else {
+ result += lastSavedMoment.format("MMMM D, YYYY");
}
- if (duration.asDays() >= 1 && duration.asYears() < 1) {
- result = `${result} ${lastSavedMoment.format("MMMM D")}`;
- }
- if (duration.asYears() >= 1) {
- result = `${result} ${lastSavedMoment.format("MMMM D, YYYY")}`;
- }
- result = `${result} (${lastSavedMoment.fromNow()})`;
+ result += ` (${lastSavedMoment.fromNow()})`;
return result;
}
}
@@ -77,11 +72,11 @@ SaveMessage.propTypes = {
PropTypes.instanceOf(Date),
PropTypes.instanceOf(moment),
PropTypes.string
- ].isRequred),
+ ]).isRequired,
};
-SaveMessage.defaultProps = {
- lastSaved: moment(),
-};
+// SaveMessage.defaultProps = {
+// lastSaved: moment(),
+// };
export default SaveMessage;
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index ff00835ed3..a68f826614 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -4,9 +4,6 @@ import moment from "moment";
import SaveMessage from "./SaveMessage";
describe("", () => {
- let lastSaved;
- let subject;
-
describe('when saved less than 1 minute ago, it displays "Saved"', () => {
[
["1 second ago", 1],
@@ -15,8 +12,8 @@ describe("", () => {
["59 seconds", 59],
].forEach(([testName, seconds]) => {
test(testName, () => {
- lastSaved = moment().subtract(seconds, "seconds");
- subject = shallow(
+ const lastSaved = moment().subtract(seconds, "seconds");
+ const subject = shallow(
);
expect(subject.text()).toEqual("Saved");
@@ -43,7 +40,7 @@ describe("", () => {
});
it('auto-updates from "Saved" to (1 minute ago)', () => {
- subject = shallow(
+ const subject = shallow(
);
expect(subject.text()).toMatch("Saved");
@@ -75,10 +72,9 @@ describe("", () => {
[364, "days", "Last saved January 2 (1 year ago)"],
[3, "years", "Last saved January 1, 2017 (3 years ago)"],
].forEach(([value, timeUnit, result]) => {
- const testName = `when saved ${value} ${timeUnit} ago, it displays "${result}"`
- test(testName, () => {
- lastSaved = moment().subtract(value, timeUnit);
- subject = shallow(
+ test(`when saved ${value} ${timeUnit} ago, it displays "${result}"`, () => {
+ const lastSaved = moment().subtract(value, timeUnit);
+ const subject = shallow(
);
expect(subject.text()).toEqual(result);
From b010620cee32392bbfcc857836a63bcde867e7dd Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Fri, 27 Mar 2020 11:22:36 -0400
Subject: [PATCH 13/18] refactor into functional component, auto-update test
broken :(
---
web/src/components/SaveMessage.js | 66 ++++++++------------------
web/src/components/SaveMessage.test.js | 28 ++++++-----
2 files changed, 37 insertions(+), 57 deletions(-)
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
index f5cc9d5155..b4bb98fb95 100644
--- a/web/src/components/SaveMessage.js
+++ b/web/src/components/SaveMessage.js
@@ -1,5 +1,5 @@
import moment from "moment";
-import React from "react";
+import React, { useEffect, useState } from "react";
import PropTypes from 'prop-types';
// Configure moment to display '1 time-unit ago' instead of 'a time-unit ago'
@@ -20,52 +20,32 @@ moment.updateLocale("en", {
},
});
-class SaveMessage extends React.Component {
- constructor(props) {
- super(props);
+const SaveMessage = ({ lastSaved }) => {
+ const [currentMoment, setCurrentMoment] = useState(() => moment());
- this.state = {
- currentMoment: moment(),
- };
- }
+ useEffect(() => {
+ let timerID = setInterval(() => setCurrentMoment(moment()), 1000);
+ return () => clearInterval(timerID);
+ });
- componentDidMount() {
- this.timerID = setInterval(() => this.updateClock(), 1000);
- }
+ const lastSavedMoment = moment(lastSaved);
+ const difference = currentMoment.diff(lastSavedMoment);
+ const duration = moment.duration(difference);
+ let result = "Last saved ";
- componentWillUnmount() {
- clearInterval(this.timerID);
- }
+ if (duration.asMinutes() < 1) return "Saved";
- updateClock() {
- this.setState({
- currentMoment: moment(),
- });
+ if (duration.asDays() < 1) {
+ result += lastSavedMoment.format("h:mm a");
+ } else if (duration.asYears() < 1) {
+ result += lastSavedMoment.format("MMMM D");
+ } else {
+ result += lastSavedMoment.format("MMMM D, YYYY");
}
- render() {
- const { lastSaved } = this.props;
- const { currentMoment } = this.state;
-
- const lastSavedMoment = moment(lastSaved);
- const difference = currentMoment.diff(lastSavedMoment);
- const duration = moment.duration(difference);
- let result = "Last saved ";
-
- if (duration.asMinutes() < 1) return "Saved";
-
- if (duration.asDays() < 1) {
- result += lastSavedMoment.format("h:mm a");
- } else if (duration.asYears() < 1) {
- result += lastSavedMoment.format("MMMM D");
- } else {
- result += lastSavedMoment.format("MMMM D, YYYY");
- }
-
- result += ` (${lastSavedMoment.fromNow()})`;
- return result;
- }
-}
+ result += ` (${lastSavedMoment.fromNow()})`;
+ return result;
+};
SaveMessage.propTypes = {
lastSaved: PropTypes.oneOfType([
@@ -75,8 +55,4 @@ SaveMessage.propTypes = {
]).isRequired,
};
-// SaveMessage.defaultProps = {
-// lastSaved: moment(),
-// };
-
export default SaveMessage;
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index a68f826614..e7e618c8c9 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -1,5 +1,6 @@
import React from "react";
-import { shallow } from "enzyme";
+import { act } from 'react-dom/test-utils';
+import { mount, shallow } from "enzyme";
import moment from "moment";
import SaveMessage from "./SaveMessage";
@@ -21,30 +22,33 @@ describe("", () => {
});
});
- describe("when observed saved time changes to 1 minute ago", () => {
- const now = new Date(2020, 0, 1, 12, 0);
- const oneMinuteFromNow = new Date(2020, 0, 1, 12, 1);
- let mockDateNow;
+ xdescribe("when observed saved time changes to 1 minute ago", () => {
+ // const now = new Date(2020, 0, 1, 12, 0);
+ // const oneMinuteFromNow = new Date(2020, 0, 1, 12, 1);
+ // let mockDateNow;
beforeEach(() => {
jest.useFakeTimers();
- mockDateNow = jest
- .spyOn(Date, "now")
- .mockReturnValueOnce(now)
- .mockReturnValue(oneMinuteFromNow);
+ // mockDateNow = jest
+ // .spyOn(Date, "now")
+ // .mockReturnValueOnce(now)
+ // .mockReturnValueOnce(now)
+ // .mockReturnValue(oneMinuteFromNow);
});
afterEach(() => {
- mockDateNow.mockRestore();
+ // mockDateNow.mockRestore();
jest.clearAllTimers();
});
it('auto-updates from "Saved" to (1 minute ago)', () => {
const subject = shallow(
-
+
);
expect(subject.text()).toMatch("Saved");
- jest.advanceTimersByTime(1000);
+ jest.advanceTimersByTime(65*1000);
+ // subject.setProps();
+ act(() => {subject.setProps()});
expect(subject.text()).toMatch(/\(1 minute ago\)$/);
});
});
From 017b419094950f0e10165f5294b8524f42dddf60 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Fri, 27 Mar 2020 11:53:14 -0400
Subject: [PATCH 14/18] use react-test-renderer for testing
---
web/src/components/SaveMessage.test.js | 57 +++++++++++++-------------
1 file changed, 29 insertions(+), 28 deletions(-)
diff --git a/web/src/components/SaveMessage.test.js b/web/src/components/SaveMessage.test.js
index e7e618c8c9..5be2c01dd0 100644
--- a/web/src/components/SaveMessage.test.js
+++ b/web/src/components/SaveMessage.test.js
@@ -1,10 +1,11 @@
import React from "react";
-import { act } from 'react-dom/test-utils';
-import { mount, shallow } from "enzyme";
+import { create, act } from "react-test-renderer";
import moment from "moment";
import SaveMessage from "./SaveMessage";
describe("", () => {
+ let subject;
+
describe('when saved less than 1 minute ago, it displays "Saved"', () => {
[
["1 second ago", 1],
@@ -14,42 +15,42 @@ describe("", () => {
].forEach(([testName, seconds]) => {
test(testName, () => {
const lastSaved = moment().subtract(seconds, "seconds");
- const subject = shallow(
-
- );
- expect(subject.text()).toEqual("Saved");
+ // https://reactjs.org/docs/test-renderer.html#testrendereract
+ act(() => {
+ subject = create();
+ })
+ expect(subject.toJSON()).toEqual("Saved");
});
});
});
- xdescribe("when observed saved time changes to 1 minute ago", () => {
- // const now = new Date(2020, 0, 1, 12, 0);
- // const oneMinuteFromNow = new Date(2020, 0, 1, 12, 1);
- // let mockDateNow;
+ describe("when observed saved time changes to 1 minute ago", () => {
+ const now = new Date(2020, 0, 1, 12, 0);
+ const oneMinuteFromNow = new Date(2020, 0, 1, 12, 1);
+ let mockDateNow;
beforeEach(() => {
jest.useFakeTimers();
- // mockDateNow = jest
- // .spyOn(Date, "now")
- // .mockReturnValueOnce(now)
- // .mockReturnValueOnce(now)
- // .mockReturnValue(oneMinuteFromNow);
+ mockDateNow = jest
+ .spyOn(Date, "now")
+ .mockReturnValueOnce(now)
+ .mockReturnValueOnce(now)
+ .mockReturnValueOnce(now)
+ .mockReturnValue(oneMinuteFromNow);
});
afterEach(() => {
- // mockDateNow.mockRestore();
+ mockDateNow.mockRestore();
jest.clearAllTimers();
});
it('auto-updates from "Saved" to (1 minute ago)', () => {
- const subject = shallow(
-
- );
- expect(subject.text()).toMatch("Saved");
- jest.advanceTimersByTime(65*1000);
- // subject.setProps();
- act(() => {subject.setProps()});
- expect(subject.text()).toMatch(/\(1 minute ago\)$/);
+ act(() => {
+ subject = create();
+ })
+ expect(subject.toJSON()).toMatch("Saved");
+ act(() => jest.advanceTimersByTime(60 * 1000));
+ expect(subject.toJSON()).toMatch(/\(1 minute ago\)$/);
});
});
@@ -78,10 +79,10 @@ describe("", () => {
].forEach(([value, timeUnit, result]) => {
test(`when saved ${value} ${timeUnit} ago, it displays "${result}"`, () => {
const lastSaved = moment().subtract(value, timeUnit);
- const subject = shallow(
-
- );
- expect(subject.text()).toEqual(result);
+ act(() => {
+ subject = create();
+ })
+ expect(subject.toJSON()).toEqual(result);
});
});
});
From f350adc4f68adc079c2fb57065e4d257549e204e Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Fri, 27 Mar 2020 11:53:24 -0400
Subject: [PATCH 15/18] update snapshots
---
.../__snapshots__/CardForm.test.js.snap | 13 ---
.../__snapshots__/ConsentBanner.test.js.snap | 5 -
.../DashboardButton.test.js.snap | 1 -
.../__snapshots__/DateField.test.js.snap | 14 +++
.../__snapshots__/DollarField.test.js.snap | 110 ++++++++----------
.../FormAndReviewList.test.js.snap | 14 ---
.../__snapshots__/Review.test.js.snap | 8 --
.../__snapshots__/ApdExport.test.js.snap | 1 -
.../activity/__snapshots__/All.test.js.snap | 1 -
.../__snapshots__/EntryDetails.test.js.snap | 9 --
.../__snapshots__/MyAccount.test.js.snap | 6 -
.../__snapshots__/Export.test.js.snap | 1 -
12 files changed, 64 insertions(+), 119 deletions(-)
diff --git a/web/src/components/__snapshots__/CardForm.test.js.snap b/web/src/components/__snapshots__/CardForm.test.js.snap
index c67df7aec8..bbaebb411f 100644
--- a/web/src/components/__snapshots__/CardForm.test.js.snap
+++ b/web/src/components/__snapshots__/CardForm.test.js.snap
@@ -33,7 +33,6 @@ exports[`card form wrapper disables the save button if canSubmit is false 1`] =
className="ds-u-margin-top--5"
>
diff --git a/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap b/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap
index 6858988a30..ead24f15ee 100644
--- a/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap
+++ b/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap
@@ -11,7 +11,6 @@ exports[`the (Activity) EntryDetails component does not render the delete button
className="nowrap visibility--screen"
>
Date: Fri, 27 Mar 2020 12:39:05 -0400
Subject: [PATCH 16/18] appease the linter
---
web/src/components/SaveMessage.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/web/src/components/SaveMessage.js b/web/src/components/SaveMessage.js
index b4bb98fb95..0c29cd557c 100644
--- a/web/src/components/SaveMessage.js
+++ b/web/src/components/SaveMessage.js
@@ -1,5 +1,5 @@
import moment from "moment";
-import React, { useEffect, useState } from "react";
+import { useEffect, useState } from "react";
import PropTypes from 'prop-types';
// Configure moment to display '1 time-unit ago' instead of 'a time-unit ago'
@@ -24,7 +24,7 @@ const SaveMessage = ({ lastSaved }) => {
const [currentMoment, setCurrentMoment] = useState(() => moment());
useEffect(() => {
- let timerID = setInterval(() => setCurrentMoment(moment()), 1000);
+ const timerID = setInterval(() => setCurrentMoment(moment()), 1000);
return () => clearInterval(timerID);
});
From f27e9d570ffe027e918cab1ad01022786bcecf95 Mon Sep 17 00:00:00 2001
From: Richard Davis
Date: Fri, 27 Mar 2020 14:13:24 -0400
Subject: [PATCH 17/18] update snapshots
---
.../__snapshots__/CardForm.test.js.snap | 13 +++
.../__snapshots__/ConsentBanner.test.js.snap | 5 +
.../DashboardButton.test.js.snap | 1 +
.../__snapshots__/DateField.test.js.snap | 14 ---
.../__snapshots__/DollarField.test.js.snap | 110 ++++++++++--------
.../FormAndReviewList.test.js.snap | 14 +++
.../__snapshots__/Review.test.js.snap | 8 ++
.../__snapshots__/ApdExport.test.js.snap | 1 +
.../activity/__snapshots__/All.test.js.snap | 1 +
.../__snapshots__/EntryDetails.test.js.snap | 9 ++
.../__snapshots__/MyAccount.test.js.snap | 6 +
.../__snapshots__/Export.test.js.snap | 1 +
12 files changed, 119 insertions(+), 64 deletions(-)
diff --git a/web/src/components/__snapshots__/CardForm.test.js.snap b/web/src/components/__snapshots__/CardForm.test.js.snap
index bbaebb411f..c67df7aec8 100644
--- a/web/src/components/__snapshots__/CardForm.test.js.snap
+++ b/web/src/components/__snapshots__/CardForm.test.js.snap
@@ -33,6 +33,7 @@ exports[`card form wrapper disables the save button if canSubmit is false 1`] =
className="ds-u-margin-top--5"
>
@@ -317,6 +324,7 @@ exports[`card form wrapper renders a success alert if message provided 1`] = `
className="ds-u-margin-top--5"
>
@@ -374,6 +383,7 @@ exports[`card form wrapper renders an error alert if message provided 1`] = `
className="ds-u-margin-top--5"
>
This is a U.S. government service. Your use indicates your consent to monitoring, recording, and no expectation of privacy. Misuse is subject to criminal and civil penalties.
This is a U.S. government service. Your use indicates your consent to monitoring, recording, and no expectation of privacy. Misuse is subject to criminal and civil penalties.
@@ -42,7 +41,6 @@ exports[`DateField wrapper component handles invalid dates day is a leap day but
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={2019}
/>
@@ -66,7 +64,6 @@ exports[`DateField wrapper component handles invalid dates day is invalid for mo
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={2019}
/>
@@ -90,7 +87,6 @@ exports[`DateField wrapper component handles invalid dates day is not set 1`] =
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={2000}
/>
@@ -114,7 +110,6 @@ exports[`DateField wrapper component handles invalid dates empty date 1`] = `
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue=""
/>
@@ -138,7 +133,6 @@ exports[`DateField wrapper component handles invalid dates month and day are not
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={2000}
/>
@@ -162,7 +156,6 @@ exports[`DateField wrapper component handles invalid dates month and year are no
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue=""
/>
@@ -186,7 +179,6 @@ exports[`DateField wrapper component handles invalid dates month is not set 1`]
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={2000}
/>
@@ -210,7 +202,6 @@ exports[`DateField wrapper component handles invalid dates month is out of range
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={2000}
/>
@@ -234,7 +225,6 @@ exports[`DateField wrapper component handles invalid dates year is 3 digits 1`]
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={200}
/>
@@ -258,7 +248,6 @@ exports[`DateField wrapper component handles invalid dates year is 5 digits 1`]
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={20000}
/>
@@ -282,7 +271,6 @@ exports[`DateField wrapper component handles invalid dates year is not set 1`] =
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue=""
/>
@@ -306,7 +294,6 @@ exports[`DateField wrapper component passes other props along to design system c
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={1944}
/>
@@ -330,7 +317,6 @@ exports[`DateField wrapper component renders properly with defaults 1`] = `
onComponentBlur={[Function]}
yearInvalid={false}
yearLabel="Year"
- yearMin={1900}
yearName="year"
yearValue={1944}
/>
diff --git a/web/src/components/__snapshots__/DollarField.test.js.snap b/web/src/components/__snapshots__/DollarField.test.js.snap
index 86ef3d9148..6de4ea8e42 100644
--- a/web/src/components/__snapshots__/DollarField.test.js.snap
+++ b/web/src/components/__snapshots__/DollarField.test.js.snap
@@ -71,29 +71,31 @@ exports[`DollarField component passes back numeric values on change, but still r
-
+
+
@@ -153,29 +155,31 @@ exports[`DollarField component renders correctly for non-numeric initial values
-
+
+
@@ -235,29 +239,31 @@ exports[`DollarField component renders correctly, adds commas to big numbers, pa
-
+
+
@@ -317,29 +323,31 @@ exports[`DollarField component renders correctly, does not add commas to small n
-
+
+
@@ -435,29 +443,31 @@ exports[`DollarField component rounds numbers when the component loses focus, bu
-
+
+
diff --git a/web/src/components/__snapshots__/FormAndReviewList.test.js.snap b/web/src/components/__snapshots__/FormAndReviewList.test.js.snap
index 0e4f174259..84ce9d40fb 100644
--- a/web/src/components/__snapshots__/FormAndReviewList.test.js.snap
+++ b/web/src/components/__snapshots__/FormAndReviewList.test.js.snap
@@ -34,6 +34,7 @@ exports[`FormAndReviewList component add button calls add event 1`] = `
/>
@@ -93,6 +94,7 @@ exports[`FormAndReviewList component expands and collapses items 2`] = `
@@ -179,6 +182,7 @@ exports[`FormAndReviewList component handles extra buttons on list items renders
initialCollapsed={false}
/>
@@ -268,6 +275,7 @@ exports[`FormAndReviewList component renders properly with just one item 1`] = `
/>
@@ -296,6 +304,7 @@ exports[`FormAndReviewList component renders properly with just one item and all
/>
@@ -340,6 +349,7 @@ exports[`FormAndReviewList component renders properly with multiple items 1`] =
/>
@@ -353,6 +363,7 @@ exports[`FormAndReviewList component renders properly with no items 1`] = `
className="form-and-review-list "
>
@@ -360,6 +371,7 @@ exports[`FormAndReviewList component renders properly with no items 1`] = `
@@ -374,6 +386,7 @@ exports[`FormAndReviewList component renders properly with no items and noDataMe
>
@@ -387,6 +400,7 @@ exports[`FormAndReviewList component renders properly without an add button if t
className="form-and-review-list "
>
diff --git a/web/src/components/__snapshots__/Review.test.js.snap b/web/src/components/__snapshots__/Review.test.js.snap
index a73fc39b98..a4a288b480 100644
--- a/web/src/components/__snapshots__/Review.test.js.snap
+++ b/web/src/components/__snapshots__/Review.test.js.snap
@@ -9,6 +9,7 @@ exports[`Review wrapper component renders properly if a delete handler is provid
|
}
editText="Edit"
+ headingLevel="3"
>
Hello
@@ -32,6 +34,7 @@ exports[`Review wrapper component renders properly if an edit handler is supplie
className="nowrap visibility--screen"
>
}
editText="Edit"
+ headingLevel="3"
>
Hello
@@ -55,6 +59,7 @@ exports[`Review wrapper component renders properly if only the required props ar
/>
}
editText="Edit"
+ headingLevel="3"
>
Hello
@@ -68,6 +73,7 @@ exports[`Review wrapper component renders properly if the edit link and edit han
/>
}
editText="Edit"
+ headingLevel="3"
>
Hello
@@ -80,6 +86,7 @@ exports[`Review wrapper component renders properly if the edit link is set 1`] =
className="nowrap visibility--screen"
>
}
editText="Edit"
+ headingLevel="3"
>
Hello
diff --git a/web/src/containers/__snapshots__/ApdExport.test.js.snap b/web/src/containers/__snapshots__/ApdExport.test.js.snap
index 852ec653d0..07133d1898 100644
--- a/web/src/containers/__snapshots__/ApdExport.test.js.snap
+++ b/web/src/containers/__snapshots__/ApdExport.test.js.snap
@@ -18,6 +18,7 @@ exports[`apd export component renders correctly 1`] = `
diff --git a/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap b/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap
index ead24f15ee..6858988a30 100644
--- a/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap
+++ b/web/src/containers/activity/__snapshots__/EntryDetails.test.js.snap
@@ -11,6 +11,7 @@ exports[`the (Activity) EntryDetails component does not render the delete button
className="nowrap visibility--screen"
>
Date: Fri, 27 Mar 2020 14:58:27 -0400
Subject: [PATCH 18/18] update changelog
---
CHANGELOG.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea14dc8fb5..57cef8855e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@ Anticipated release: April 6, 2020
#### 🚀 New features
+- The header displays the time ago since the APD was last saved ([#2104])
+
#### 🐛 Bugs fixed
#### ⚙️ Behind the scenes
@@ -12,4 +14,6 @@ Anticipated release: April 6, 2020
# Previous releases
-See our [release history](https://github.com/18F/cms-hitech-apd/releases)
\ No newline at end of file
+See our [release history](https://github.com/18F/cms-hitech-apd/releases)
+
+[#2104]: https://github.com/18F/cms-hitech-apd/issues/2104