From bbc13689a827b4950aba3eeae8fe46affe517142 Mon Sep 17 00:00:00 2001 From: gvdp Date: Mon, 26 Oct 2020 10:29:09 +0100 Subject: [PATCH] refactor: replace momentjs in desktop (#8959) Co-authored-by: Jennifer Shehane --- .../cypress/integration/runs_list_spec.js | 29 +++++------ .../cypress/integration/utils_spec.js | 11 ++++ packages/desktop-gui/package.json | 2 +- .../duration-timer/duration-timer-store.js | 10 ++-- .../desktop-gui/src/lib/configure-moment.js | 24 --------- packages/desktop-gui/src/lib/utils.js | 51 ++++++++++++++++++- packages/desktop-gui/src/main.jsx | 2 - .../desktop-gui/src/runs/runs-list-item.jsx | 25 ++++++--- packages/desktop-gui/src/runs/runs-store.js | 6 +-- yarn.lock | 5 ++ 10 files changed, 105 insertions(+), 60 deletions(-) delete mode 100644 packages/desktop-gui/src/lib/configure-moment.js diff --git a/packages/desktop-gui/cypress/integration/runs_list_spec.js b/packages/desktop-gui/cypress/integration/runs_list_spec.js index f960ab0e2a..862acdb050 100644 --- a/packages/desktop-gui/cypress/integration/runs_list_spec.js +++ b/packages/desktop-gui/cypress/integration/runs_list_spec.js @@ -1,5 +1,3 @@ -const moment = require('moment') - describe('Runs List', function () { beforeEach(function () { cy.fixture('user').as('user') @@ -72,7 +70,7 @@ describe('Runs List', function () { context('api server connection', function () { beforeEach(function () { - const timestamp = moment('2016-12-19T10:00:00').valueOf() + const timestamp = new Date(2016, 11, 19, 10, 0, 0).valueOf() cy.clock(timestamp) this.getCurrentUser.resolve(this.user) @@ -100,11 +98,12 @@ describe('Runs List', function () { context('displays each run\'s data', function () { beforeEach(function () { cy.get('.runs-container li').first().as('firstRunRow') - cy.get('.runs-container li').eq(1).as('runRow') + cy.get('.runs-container li').eq(1).as('secondRunRow') + cy.get('.runs-container li').eq(3).as('fourthRunRow') }) it('displays build num', function () { - cy.get('@runRow').contains(`#${this.runs[1].buildNumber}`) + cy.get('@secondRunRow').contains(`#${this.runs[1].buildNumber}`) }) it('displays commit info', function () { @@ -113,14 +112,14 @@ describe('Runs List', function () { }) it('display no info msg & does not display avatar', () => { - cy.get('@runRow').within(function () { + cy.get('@secondRunRow').within(function () { cy.get('.user-avatar').should('not.exist') cy.contains('No commit info found') }) }) it('displays platform info', () => { - cy.get('@runRow').within(function () { + cy.get('@secondRunRow').within(function () { cy.contains(this.runs[1].instances[0].platform.osVersionFormatted) cy.contains(this.runs[1].instances[0].platform.browserName) cy.get('.fa-apple') @@ -138,24 +137,24 @@ describe('Runs List', function () { }) it('displays totals', function () { - cy.get('@runRow').contains(this.runs[1].totalFailed) - cy.get('@runRow').contains(this.runs[1].totalPassed) + cy.get('@secondRunRow').contains(this.runs[1].totalFailed) + cy.get('@secondRunRow').contains(this.runs[1].totalPassed) }) it('displays times', function () { - cy.get('@runRow').contains('a few secs ago') - cy.get('@runRow').contains('00:16') + cy.get('@secondRunRow').contains('a few secs ago') + cy.get('@secondRunRow').contains('00:16') }) it('displays separate timers for incomplete runs', function () { - cy.get('@firstRunRow').contains('24:47') - cy.get('.runs-container li').eq(3).contains('45:47') + cy.get('@firstRunRow').contains('12:24:47') + cy.get('@fourthRunRow').contains('12:45:47') .then(() => { cy.tick(1000) }) - cy.get('@firstRunRow').contains('24:48') - cy.get('.runs-container li').eq(3).contains('45:48') + cy.get('@firstRunRow').contains('12:24:48') + cy.get('@fourthRunRow').contains('12:45:48') }) context('spec display', function () { diff --git a/packages/desktop-gui/cypress/integration/utils_spec.js b/packages/desktop-gui/cypress/integration/utils_spec.js index b41395f8b6..b5df33ab44 100644 --- a/packages/desktop-gui/cypress/integration/utils_spec.js +++ b/packages/desktop-gui/cypress/integration/utils_spec.js @@ -1,3 +1,5 @@ +import dayjs from 'dayjs' + const utils = require('../../src/lib/utils') describe('durationFormatted', function () { @@ -26,6 +28,15 @@ describe('durationFormatted', function () { }) }) +describe('getFormattedTimeFromNow', function () { + it('displays time a minute ago', () => { + const now = dayjs() + const dateInPast = now.subtract(1, 'minute').toISOString() + + expect(utils.getFormattedTimeFromNow(dateInPast)).to.eq('a min ago') + }) +}) + describe('stripLeadingCyDirs', function () { it('strips leading cypress directories from spec', function () { expect(utils.stripLeadingCyDirs('cypress/integration/login_spec.js')).to.eq('login_spec.js') diff --git a/packages/desktop-gui/package.json b/packages/desktop-gui/package.json index ce4d67f71b..2cdccc17f1 100644 --- a/packages/desktop-gui/package.json +++ b/packages/desktop-gui/package.json @@ -28,6 +28,7 @@ "cross-env": "6.0.3", "cypress-multi-reporters": "1.4.0", "cypress-react-unit-test": "4.11.2", + "dayjs": "^1.9.3", "fira": "cypress-io/fira#fb63362742eea8cdce0d90825ab9264d77719e3d", "gravatar": "1.8.0", "human-interval": "1.0.0", @@ -36,7 +37,6 @@ "mobx": "5.15.4", "mobx-react": "6.1.8", "mobx-react-devtools": "6.1.1", - "moment": "2.27.0", "prop-types": "15.7.2", "rc-collapse": "2.0.0", "react": "16.8.6", diff --git a/packages/desktop-gui/src/duration-timer/duration-timer-store.js b/packages/desktop-gui/src/duration-timer/duration-timer-store.js index e51a6628f6..6a02baee3f 100644 --- a/packages/desktop-gui/src/duration-timer/duration-timer-store.js +++ b/packages/desktop-gui/src/duration-timer/duration-timer-store.js @@ -1,16 +1,16 @@ import { observable, computed, action } from 'mobx' -import moment from 'moment' import Timer from './duration-timer-model' +import dayjs from 'dayjs' -class DurationTimer { +class TimerStore { @observable isRunning = false @observable timer @observable startTime constructor (startTime) { this.timer = new Timer() - this.startTime = moment(startTime) + this.startTime = dayjs(startTime) } @computed get mainDisplay () { @@ -20,7 +20,7 @@ class DurationTimer { @action measure () { if (!this.isRunning) return - this.timer.milliseconds = moment().diff(this.startTime) + this.timer.milliseconds = dayjs().diff(this.startTime) this.timerId = setTimeout(() => { return this.measure() @@ -41,4 +41,4 @@ class DurationTimer { } } -export default DurationTimer +export default TimerStore diff --git a/packages/desktop-gui/src/lib/configure-moment.js b/packages/desktop-gui/src/lib/configure-moment.js deleted file mode 100644 index c60653365e..0000000000 --- a/packages/desktop-gui/src/lib/configure-moment.js +++ /dev/null @@ -1,24 +0,0 @@ -import moment from 'moment' - -const configureMoment = () => { - moment.updateLocale('en', { - relativeTime: { - future: 'in %s', - past: '%s ago', - s: 'a few secs', - ss: '%d secs', - m: 'a min', - mm: '%d mins', - h: 'an hour', - hh: '%d hours', - d: 'a day', - dd: '%d days', - M: 'a month', - MM: '%d months', - y: 'a year', - yy: '%d years', - }, - }) -} - -export default configureMoment diff --git a/packages/desktop-gui/src/lib/utils.js b/packages/desktop-gui/src/lib/utils.js index cd3f18f59c..29c93c02d0 100644 --- a/packages/desktop-gui/src/lib/utils.js +++ b/packages/desktop-gui/src/lib/utils.js @@ -1,6 +1,31 @@ import _ from 'lodash' import gravatar from 'gravatar' -import duration from '../../../server/lib/util/duration' +import dayjs from 'dayjs' +import relativeTime from 'dayjs/plugin/relativeTime' +import updateLocale from 'dayjs/plugin/updateLocale' +import duration from 'dayjs/plugin/duration' + +dayjs.extend(duration) +dayjs.extend(relativeTime) +dayjs.extend(updateLocale) +dayjs.updateLocale('en', { + relativeTime: { + future: 'in %s', + past: '%s ago', + s: 'a few secs', + ss: '%d secs', + m: 'a min', + mm: '%d mins', + h: 'an hour', + hh: '%d hours', + d: 'a day', + dd: '%d days', + M: 'a month', + MM: '%d months', + y: 'a year', + yy: '%d years', + }, +}) const cyDirRegex = /^cypress\/integration\//g @@ -10,7 +35,29 @@ const osIconLookup = { linux: 'linux', } -export const durationFormatted = duration.format +export const getFormattedTimeFromNow = (timeAsIsoString) => { + return dayjs(timeAsIsoString).fromNow() +} + +export const durationFormatted = (durationInMs) => { + if (durationInMs < 1000) { + return `${durationInMs}ms` + } + + const dayDuration = dayjs.duration(durationInMs) + + const durationSecs = dayDuration.seconds() ? `${dayDuration.seconds()}` : '' + const durationMins = dayDuration.minutes() ? `${dayDuration.minutes()}` : '' + const durationHrs = dayDuration.hours() ? `${dayDuration.hours()}` : '' + + const total = _.compact([ + durationHrs, + _.padStart(durationMins, 2, '0'), + _.padStart(durationSecs, 2, '0'), + ]) + + return total.join(':') +} export const osIcon = (osName) => { if (!osName) return '' diff --git a/packages/desktop-gui/src/main.jsx b/packages/desktop-gui/src/main.jsx index fb2a75ab7f..c303289578 100644 --- a/packages/desktop-gui/src/main.jsx +++ b/packages/desktop-gui/src/main.jsx @@ -5,14 +5,12 @@ import { render } from 'react-dom' import ipc from './lib/ipc' import handleGlobalErrors from './lib/handle-global-errors' -import momentOverrides from './lib/configure-moment' import App from './app/app' configureMobx({ enforceActions: 'observed' }) handleGlobalErrors() -momentOverrides() if (window.env === 'test' || window.env === 'development') { window.toJS = toJS diff --git a/packages/desktop-gui/src/runs/runs-list-item.jsx b/packages/desktop-gui/src/runs/runs-list-item.jsx index ebef2789ba..06e88fb646 100644 --- a/packages/desktop-gui/src/runs/runs-list-item.jsx +++ b/packages/desktop-gui/src/runs/runs-list-item.jsx @@ -1,11 +1,20 @@ import _ from 'lodash' -import moment from 'moment' import React, { Component } from 'react' import Tooltip from '@cypress/react-tooltip' import { BrowserIcon } from '@packages/ui-components' - import TimerDisplay from '../duration-timer/TimerDisplay' -import { osIcon, gravatarUrl, getStatusIcon, durationFormatted, browserNameFormatted, browserVersionFormatted, stripLeadingCyDirs, stripSharedDirsFromDir2 } from '../lib/utils' + +import { + browserNameFormatted, + browserVersionFormatted, + durationFormatted, + getFormattedTimeFromNow, + getStatusIcon, + gravatarUrl, + osIcon, + stripLeadingCyDirs, + stripSharedDirsFromDir2, +} from '../lib/utils' const RunDuration = ({ run }) => { // Run was blocked due to exceeding limit @@ -37,7 +46,7 @@ const RunDuration = ({ run }) => { // Run is still going if (run.createdAt) { return ( - + ) } @@ -66,7 +75,7 @@ export default class RunsListItem extends Component {
- { run.commit && run.commit.branch ? + {run.commit && run.commit.branch ? {run.commit.branch} {this._displaySpec() ? ' / ' : null} @@ -108,12 +117,12 @@ export default class RunsListItem extends Component {
{' '} - {moment(run.createdAt).fromNow() === '1 secs ago' ? '1 sec ago' : moment(run.createdAt).fromNow()} + {getFormattedTimeFromNow(run.createdAt)}
- +
@@ -253,7 +262,7 @@ export default class RunsListItem extends Component { _browserIcon = () => { const browserName = _.get(this.props.run, 'instances[0].platform.browserName', '') - return browserName ? : null + return browserName ? : null } _browserDisplay = () => { diff --git a/packages/desktop-gui/src/runs/runs-store.js b/packages/desktop-gui/src/runs/runs-store.js index 3590391f89..f1c2e1fccc 100644 --- a/packages/desktop-gui/src/runs/runs-store.js +++ b/packages/desktop-gui/src/runs/runs-store.js @@ -1,8 +1,8 @@ import _ from 'lodash' -import { observable, action } from 'mobx' -import moment from 'moment' +import { action, observable } from 'mobx' import Run from './run-model' +import dayjs from 'dayjs' export class RunsStore { @observable runs = [] @@ -21,7 +21,7 @@ export class RunsStore { return new Run(run) }) - this.lastUpdated = moment().format('h:mm:ssa') + this.lastUpdated = dayjs().format('h:mm:ssa') this.error = null this.isLoading = false this.isLoaded = true diff --git a/yarn.lock b/yarn.lock index 88138a64ba..9e84254cbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12031,6 +12031,11 @@ daty@^1.0.7: diff-dates "^1.0.0" formatoid "^1.0.0" +dayjs@^1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.9.3.tgz#b7f94b22ad2a136a4ca02a01ab68ae893fe1a268" + integrity sha512-V+1SyIvkS+HmNbN1G7A9+ERbFTV9KTXu6Oor98v2xHmzzpp52OIJhQuJSTywWuBY5pyAEmlwbCi1Me87n/SLOw== + days@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/days/-/days-1.1.1.tgz#b039d1e5ad5335ca689401855546f02d4cfcb362"