Migrate over time-from-now composition

This commit is contained in:
rijkvanzanten
2020-02-07 15:17:16 -05:00
parent c4f90b724a
commit 98b43cc294
5 changed files with 146 additions and 2 deletions

View File

@@ -58,6 +58,7 @@
"eslint-plugin-vue": "^5.0.0",
"html-loader": "^0.5.5",
"lint-staged": "^9.5.0",
"mockdate": "^2.0.5",
"prettier": "^1.19.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",

View File

@@ -1,10 +1,11 @@
# Compositions
Compositions are reusable snippets of functionality that can be used in Vue components.
Compositions are reusable pieces of logic that can be used inside Vue components (Composition API required).
## Table of Contents
* [Event Listener](#event-listener)
* [Time from Now](#time-from-now)
* [Window Size](#window-size)
## Event Listener
@@ -32,6 +33,27 @@ export default createComponent({
});
```
## Time from Now
Returns ref string time from current datetime based on date-fns formatDistance.
### Usage
```js
import { createComponent } from '@vue/composition-api';
import useTimeFromNow from '@/compositions/time-from-now';
export default createComponent({
setup() {
const date = new Date('2020-01-01T13:55');
const timeFromNow = useTimeFromNow(date);
}
});
```
The composition accepts an optional second parameter that controls how often the value is update. You can set this to `0` if you don't want the value to update at all.
## Window Size
Returns a `ref` of `width` and `height` of the current window size. Updates the value on window resizes.

View File

@@ -0,0 +1,90 @@
import { Ref } from '@vue/composition-api';
import useTimeFromNow from './time-from-now';
import mountComposition from '../../.jest/mount-composition';
import mockdate from 'mockdate';
describe('Compositions / Event Listener', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
mockdate.reset();
});
it('Formats the date relative', () => {
const now = new Date();
let timeAgo: Ref<string>;
let timeAhead: Ref<string>;
mountComposition(() => {
timeAgo = useTimeFromNow(new Date(now.getTime() - 5 * 60 * 1000));
timeAhead = useTimeFromNow(new Date(now.getTime() + 5 * 60 * 1000));
});
expect(timeAgo!.value).toBe('5 minutes ago');
expect(timeAhead!.value).toBe('in 5 minutes');
});
it('Updates the ref every minute by default', () => {
mockdate.set('2020-01-01T12:00:00');
const now = new Date();
const component = mountComposition(() => {
const timeAgo = useTimeFromNow(new Date(now.getTime() - 5 * 60 * 1000));
return { timeAgo };
});
expect((component.vm as any).timeAgo).toBe('5 minutes ago');
mockdate.set('2020-01-01T12:01:00');
jest.runTimersToTime(60000);
expect(setInterval).toHaveBeenCalledTimes(1);
expect((component.vm as any).timeAgo).toBe('6 minutes ago');
});
it('Does not automatically update if 0 is passed for autoUpdate param', () => {
mockdate.set('2020-01-01T12:00:00');
const now = new Date();
const component = mountComposition(() => {
const timeAgo = useTimeFromNow(new Date(now.getTime() - 5 * 60 * 1000), 0);
return { timeAgo };
});
expect((component.vm as any).timeAgo).toBe('5 minutes ago');
mockdate.set('2020-01-01T12:01:00');
jest.runTimersToTime(60000);
expect(setInterval).toHaveBeenCalledTimes(0);
expect((component.vm as any).timeAgo).toBe('5 minutes ago');
});
it('Clears the interval when the component is unmounted', () => {
mockdate.set('2020-01-01T12:00:00');
const now = new Date();
const component = mountComposition(() => {
const timeAgo = useTimeFromNow(new Date(now.getTime() - 5 * 60 * 1000));
return { timeAgo };
});
expect((component.vm as any).timeAgo).toBe('5 minutes ago');
mockdate.set('2020-01-01T12:01:00');
jest.runTimersToTime(60000);
expect(setInterval).toHaveBeenCalledTimes(1);
component.destroy();
mockdate.set('2020-01-01T12:01:00');
jest.runTimersToTime(60000);
expect(setInterval).toHaveBeenCalledTimes(1);
});
});

View File

@@ -0,0 +1,26 @@
import { onMounted, onUnmounted, ref } from '@vue/composition-api';
import formatDistance from 'date-fns/formatDistance';
export default function useFormatDistance(date: Date | number, autoUpdate: number = 60000) {
let interval: number;
const formatOptions = {
addSuffix: true
};
const formattedDate = ref(formatDistance(date, new Date(), formatOptions));
if (autoUpdate !== 0) {
onMounted(() => {
interval = setInterval(() => {
formattedDate.value = formatDistance(date, new Date(), formatOptions);
}, autoUpdate);
});
onUnmounted(() => {
clearInterval(interval);
});
}
return formattedDate;
}

View File

@@ -9384,6 +9384,11 @@ mkdirp@0.5.1, mkdirp@0.x, mkdirp@^0.5.1, mkdirp@~0.5.1, mkdirp@~0.5.x:
dependencies:
minimist "0.0.8"
mockdate@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/mockdate/-/mockdate-2.0.5.tgz#70c6abf9ed4b2dae65c81dfc170dd1a5cec53620"
integrity sha512-ST0PnThzWKcgSLyc+ugLVql45PvESt3Ul/wrdV/OPc/6Pr8dbLAIJsN1cIp41FLzbN+srVTNIRn+5Cju0nyV6A==
moment@^2.18.1:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
@@ -10317,7 +10322,7 @@ pify@^4.0.1:
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
pinia@^0.0.5:
pinia@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/pinia/-/pinia-0.0.5.tgz#e95fde7c3de5cdef1d4bd71fa0d9c3110862c641"
integrity sha512-EF3LpCYsA1VSm9EeCK87UHA66NFM/7++D0qnWTzSPgQ+UKoUQytWsXat777bj9WDzjNELxKlyP3Ifv44IURi2g==