Pure Green Express Blog - What Is Mail Order Marijuana?
Marijuana is widely known as a drug. In a lot of countries using marijuana is forbidden. But in some countries, this is a widely known legal plant. A lot of people like marijuana because it has a big influence on mood. This plant changes your perception of the world and you feel different. Besides, frequently using marijuana can be very harmful to your health. Thus, before using marijuana you need to think about it and be very careful.
Many people like to smoke marijuana in hand-rolled cigarettes. Such type of cigarettes is called joints. Some people prefer marijuana cigars. These cigars are partly or completely filled with marijuana. Besides, people can use marijuana in food. They can add cannabis in cakes and candies. Some people prefer to drink tea with marijuana. Some special types of marijuana are used for medical purposes. However, there are a lot of others types of this plant using.
How to Buy Marijuana Products Online?
Canada mail order marijuana is very popular now. Nowadays, you can order weed online in Canada and many others countries. You just need to have the Internet access. There is a big variety of websites. These websites are very popular among teens and young people. These websites offer different types of marijuana for sales. You can order cannabis at any time of the night and day. So, as you can see, this is not very difficult to order marijuana online. In our modern world, the words combination mail order marijuana is widely known.
If you make your order, you need to give your address. The marijuana sellers sent your order to the provided address. It may be very dangerous because these websites in most cases are illegal. You need to keep in mind that these websites are illegal almost in all the countries. However, people do not pay attention to this. They go on smoking marijuana. Besides, these sites are not reliable because such companies do not work for a long time. If you make an order, you will need to send money to this company for your order. This is the time when you need to be very cautious. You should understand that the illegal website is the unreliable website. Such a website can stop working at any time of the day or night. If you send money there is no guarantee that you will receive your marijuana.
If you have decided to buy marijuana online, there are a lot of things you need to think about. You need to choose the reliable website. This is the most important thing if you want to receive your marijuana. A reliable website should have a big variety of marijuana products. The sellers should give you all the information about the marijuana product which you have chosen. You need to discuss it with your friends. Maybe they know some useful information how to order marijuana in the right way. There are a lot of websites which just want to take your money. This is the main task of bad websites. So, you need to be very careful.
There are some legal websites which sell marijuana and you can buy marijuana online legally. These companies sell medical cannabis. Legal Weed Fly is one of them. This is a very popular website which sells medical marijuana flowers. Legal Weed Fly provides customers with high-quality medical marijuana products. Such types of companies are popular not only in America. They have customers in a lot of countries of the world. A lot of people from all over the world use marijuana as a treatment.
As you can see there are some health benefits to using marijuana. People who suffer from insomnia, chronic pain, depression, and anxiety can use marijuana as a medicine. It is known that marijuana can relieve chronic pain. Besides, marijuana can improve your mood so it can relieve the depression or stress and you will feel better. Marijuana is a good treatment for nausea. You can use marijuana to relieve muscle spasm.
What are the Benefits of Mailing Weed in Canada?
There are a lot of people who received their orders and continue to order marijuana online and do not worry about anything. Besides, there are some benefits to buying marijuana online. First of all, this is very comfortable because there is no need to walk around the city to buy marijuana. There are a lot of people who cannot leave your home or they do not know what to choose. In such a case, online sellers of marijuana can be very helpful. They can give you advice on what to choose. Ordering marijuana on the website is a very good option. You just need to choose cannabis on the Internet and fill in your information. Secondly, there is a big choice of marijuana products on the websites. You can order what you just like. Maybe you want to try something special and do not know what to choose. Thirdly, some types of marijuana, in some cases, are used as medicine. If you are looking for this special type of marijuana, there is a big possibility to find it on the website. You can ask online sellers about it. Special types of cannabis can relax you and improve your mood. Besides, it helps to fall asleep. That is why people use some special types of marijuana as a medicine.
So, nowadays you can order marijuana products online at any time. But you need to choose the reliable websites. This is not a very easy task. There are a lot of questionable companies. You need to be very careful because a lot of websites just want to take your money. There is a big chance that you will never get your marijuana products. That is why you need to buy marijuana from the reliable sources. Do not forget that some types of marijuana have health benefits. You can use marijuana as a treatment for chronic pain, muscle spasm, nausea, stress, depression, and insomnia.


text:
Texas demands documents from Google
By Brendan Sasso - 06/21/12 08:15 PM EDT
The Texas Attorney General's office is suing Google, demanding that the Web giant turn over documents it claims were illegally withheld from an antitrust investigation.
In a filing in state court earlier this week, Attorney General Greg Abbott said Google withheld a "large volume of documents" based on the claim that they were privileged attorney-client communications.
But Abbott argued that Google failed to meet its burden to demonstrate that many of the documents actually should be exempt from the investigation.
"We have shared hundreds of thousands of documents with the Texas Attorney General, and we are happy to answer any questions that regulators have about our business," a Google spokesman said in a statement.
Texas is investigating whether Google manipulates its search results to ensure that its own services, such as YouTube, Google Maps and Google Plus, appear above its rivals.
Google's competitors argue that the company shouldn't be allowed to use its dominant search engine — which has about a 65 percent market share — to stifle competition.
The Federal Trade Commission and European regulators are conducting their own parallel antitrust investigations into Google over similar issues.
The company says there is nothing unfair about its search rankings. Even if the results did boost Google products, the company says, it wouldn't be illegal.

redpajama_set_name: RedPajamaCommonCrawl


text:
Jordan Rhodes
Lee Novak desperate for sweet taste of Huddersfield Town success
IT'S been a long and winding road to Wembley for Lee Novak, so it's no wonder the Town striker is desperate to make the most of today's big promotion opportunity.
Doug Thomson
Lee Novak gets in a header against MK Dons
IT'S been a long and winding road to Wembley for Lee Novak, so it's no wonder the Huddersfield Town striker is desperate to make the most of today's big promotion opportunity.
Five years ago, the Geordie frontman was wondering what the future had in store after jumping ship ahead of Gretna's descent into football oblivion.
Now the 23-year-old is aiming to help Town earn a place in the Championship by beating Sheffield United in the eagerly-awaited League I play-off final.
Novak had come through the youth system at Gretna, who made the Scottish Cup final, then the Scottish Premier League, then became defunct in the space of three years from 2006-08.
Having foreseen the financial problems which were looming, Novak, then 18, took a gamble by returning to his native Tyneside in 2007 to play for Newcastle Blue Star.
They were also to disappear off the map, but not before the frontman had moved from the Northern Premier League to the Conference with Gateshead.
Novak, who bagged 29 goals for Blue Star, had failed to impress Stockport in trials during the 2008 close-season.
But his form for the former Football League side soon had higher-level clubs flocking to watch, and then-Town boss Lee Clark landed the player for £150,000 in January 2009.
Novak was loaned back to Gateshead for the rest of that season, finishing with 27 goals and helping them win the Blue Square North play-offs.
Now, after two play-off failures with Town, the 23-year-old is desperate to celebrate another final victory.
"When I left Gretna, if anyone had told me I'd be playing at Wembley within five years, I'd have said they were mad," he smiled after taking a look around the national stadium on Thursday.
"I thought leaving Gretna might have been the end for me in terms of professional football.
"Then, when I signed for Gateshead (in September 2008), I said I would give myself until the end of that season.
"I was looking into job opportunities in case it didn't work out and was seriously thinking of going into personal training.
"Thankfully, I got my chance with Town and I'll always be grateful. Now I just want to keep going and help the club."
The exploits of 40-goal hit man and good mate Jordan Rhodes (the pair room together on away trips) mean Novak has been somewhat in the shadows despite his own impressive haul of 17 goals.
But the industrious forward is happy to let Rhodes take the plaudits.
"He deserves all the attention he gets because he's a great player and a great lad," said the man who set up Rhodes' breakthrough headed goal in the 2-0 semi-final first leg win at MK Dons with a superb deep cross from the left touchline.
"I'm just happy to be in the side and to be doing my bit, and I'm really pleased with the way things have gone this time."
After netting 14 goals in his debut campaign, when Town went out in the play-off semis to Millwall, Novak had a tough time of it last term.
Injuries limited him to 15 starts, 24 outings from the bench and five goals.
"It was all a bit horrible really," he admitted.
"I didn't get a decent pre-season so I was always trying to catch up and I never did.
"Even though I didn't figure in the game, the play-off final defeat (by Peterborough at Old Trafford) pretty much put the tin lid on it.
"I knew I had to hit the ground running this time, and I worked hard over the summer break to make sure I was in the best shape I could be."
Novak notched Town's first goal of pre-season, in a 1-0 win on very familiar territory at Gateshead, and grabbed four more in friendlies before the serious business got under way.
He'd certainly take an 18th of the competitive campaign, and 37th for the club, this afternoon, but insists the end result is the only thing that matters.
"We're strong as a squad and focused as a squad," he added.
"The lads who don't play are always totally behind those who do, which is important.
"Sheffield United came down from the Championship last season and will feel they should be back there.
"But we haven't been there in a long time (11 years) and feel we deserve to get back.
"We've got ourselves into a great position to achieve our aim and we can't wait for the game to come around."
Lee Clark
Sheffield Wednesday FCSheffield Wednesday transfer latest as fresh update emerges on in-demand Haydon RobertsThe 19-year-old defender is likely to be loaned out by Brighton and Hove Albion in the January transfer window.
Jordan Storey explains why he left Preston North End for Sheffield Wednesday
Sheffield Wednesday FCThe 24-year-old has joined the Owls on loan and could make his debut against Oxford United this weekend.
Sheffield United transfer state of play: Heckingbottom's aim, incomings, outgoings, Berge latest
Sheffield United FCThe window closes in 11 days' time and the Blades are expected to be busy going into the final stages
Karl Robinson coy on Jermain Defoe transfer link ahead of Oxford United v Sheffield Wednesday
Sheffield Wednesday FCThe former England international is a free agent after leaving Rangers earlier this month.
Huddersfield Town on-loan striker prospect signs new long-term deal
Huddersfield Town FCCentre forward Kieran Phillips, currently on loan with League Two Walsall, has commited his long-term future to the Terriers by putting pen to paper on a new three-year deal
Sheffield United FCLys Mousset's Sheffield United fitness issues addressed as striker warned 'talent is not enough'The French forward is still not fit to return to the team as manager Paul Heckingbottom tells him he must make sacrifices
Reading eye Andy Carroll boost and two key player returns ahead of Huddersfield Town clash
Huddersfield Town FCThe former Liverpool, Newcastle United and England striker is out of contract with the Championship strugglers but a deal is on the table, while two defenders could return


text:
import { fireEvent } from '@testing-library/react'
import { renderHook } from '@testing-library/react-hooks'
import { sleep, waitFor } from './test.utils'

import { useIdleTimer } from '../src'
import { timers, createMocks } from '../src/utils/timers'

describe('useIdleTimer', () => {
  let props

  const idleTimer = () => {
    return renderHook(() => useIdleTimer(props))
  }

  beforeEach(() => {
    props = {
      timeout: undefined,
      promptTimeout: undefined,
      element: undefined,
      events: undefined,
      timers: undefined,
      immediateEvents: undefined,
      onPrompt: undefined,
      onIdle: undefined,
      onActive: undefined,
      onAction: undefined,
      onMessage: undefined,
      debounce: undefined,
      throttle: undefined,
      eventsThrottle: undefined,
      startOnMount: undefined,
      startManually: undefined,
      stopOnIdle: undefined,
      capture: undefined,
      passive: undefined,
      crossTab: undefined,
      name: undefined,
      syncTimers: undefined,
      leaderElection: undefined
    }
  })

  describe('useIdleTimer', () => {
    describe('lifecycle', () => {
      it('Should unmount before unload', async () => {
        props.crossTab = true
        props.debounce = 200
        props.onAction = jest.fn()
        idleTimer()
        fireEvent.mouseDown(document)
        await sleep(200)
        expect(props.onAction).toHaveBeenCalledTimes(1)
        fireEvent(window, new Event('beforeunload'))
        fireEvent.mouseDown(document)
        await sleep(200)
        expect(props.onAction).toHaveBeenCalledTimes(1)
      })

      it('Should compare sanity check timestamps', () => {
        jest.useFakeTimers()
        props.timeout = 10000
        props.onIdle = jest.fn()
        const start = Date.now()
        const { result } = idleTimer()

        expect(result.current.isIdle()).toBe(false)
        jest.setSystemTime(start + props.timeout)
        fireEvent.mouseDown(document)

        expect(result.current.isIdle()).toBe(true)
        expect(props.onIdle).toHaveBeenCalledTimes(1)
        jest.useRealTimers()
      })
    })

    describe('.props', () => {
      describe('.element', () => {
        it('Should set custom element', async () => {
          props.element = window
          props.timeout = 200
          props.onActive = jest.fn()
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(props.element)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should not bind events on parent', async () => {
          props.element = document
          props.timeout = 200
          props.onActive = jest.fn()

          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())

          fireEvent.mouseDown(window)
          expect(props.onActive).toHaveBeenCalledTimes(0)

          fireEvent.mouseDown(props.element)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should update dynamically', () => {
          props.element = document
          props.onAction = jest.fn()
          props.eventsThrottle = 0
          props.startOnMount = false

          const { rerender } = idleTimer()
          fireEvent.mouseDown(document)
          expect(props.onAction).toBeCalledTimes(1)

          props.element = window
          rerender()
          fireEvent.mouseDown(window)
          expect(props.onAction).toBeCalledTimes(2)
        })

        it('Should should not start when startManually is set and updated dynamically', () => {
          props.element = document
          props.onAction = jest.fn()
          props.startManually = true
          props.eventsThrottle = 0

          const { rerender, result } = idleTimer()
          result.current.start()
          fireEvent.mouseDown(document)
          expect(props.onAction).toBeCalledTimes(1)

          props.element = window
          rerender()
          fireEvent.mouseDown(window)
          expect(props.onAction).toBeCalledTimes(1)
        })

        it('Should should start immediately when startOnMount is set and updated dynamically', async () => {
          props.element = document
          props.timeout = 200
          props.onAction = jest.fn()
          props.onIdle = jest.fn()
          props.startOnMount = true
          props.eventsThrottle = 0

          const { rerender, result } = idleTimer()
          result.current.start()
          fireEvent.mouseDown(document)
          expect(props.onAction).toBeCalledTimes(1)

          props.element = window
          rerender()

          fireEvent.mouseDown(window)
          expect(props.onAction).toBeCalledTimes(2)

          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toBeCalledTimes(1)
        })

        it('Should memoize element', () => {
          props.element = window
          props.timeout = 200
          props.startOnMount = false
          props.startManually = true
          props.onAction = jest.fn()
          props.eventsThrottle = 0
          const { result, rerender } = idleTimer()
          result.current.start()
          fireEvent.mouseDown(window)
          expect(props.onAction).toHaveBeenCalledTimes(1)
          props.element = window
          rerender(props)
          fireEvent.mouseDown(window)
          expect(props.onAction).toHaveBeenCalledTimes(2)
        })
      })

      describe('.events', () => {
        it('Should set custom events', async () => {
          props.onAction = jest.fn()
          props.events = ['mousedown']
          props.timeout = 200

          idleTimer()

          fireEvent.keyPress(document)
          expect(props.onAction).toHaveBeenCalledTimes(0)

          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })

        it('Should update dynamically', () => {
          props.onAction = jest.fn()
          props.events = ['mousedown']
          props.eventsThrottle = 0

          const { rerender } = idleTimer()
          fireEvent.mouseDown(document)
          expect(props.onAction).toBeCalledTimes(1)

          props.events = ['keypress']
          rerender(props)

          fireEvent.mouseDown(document)
          fireEvent.keyPress(document)
          fireEvent.keyPress(document)
          expect(props.onAction).toBeCalledTimes(3)
        })

        it('Should memoize events', async () => {
          props.events = ['mousedown', 'mousemove']
          props.timeout = 200
          props.startOnMount = false
          props.startManually = true
          props.onAction = jest.fn()
          props.eventsThrottle = 0
          const { result, rerender } = idleTimer()
          result.current.start()
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
          props.events = ['mousedown', 'mousemove']
          rerender(props)
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(2)
        })
      })

      describe('.immediateEvents', () => {
        it('Should call idle immediately on immediate event', () => {
          props.immediateEvents = ['mousedown']
          const { result } = idleTimer()
          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(true)
        })

        it('Should concat events', () => {
          props.eventsThrottle = 0
          props.events = ['mousemove']
          props.immediateEvents = ['mousedown']
          props.startOnMount = false
          const { result } = idleTimer()
          fireEvent.mouseMove(document)
          expect(result.current.isIdle()).toBe(false)
          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(true)
        })

        it('Should update dynamically', () => {
          props.eventsThrottle = 0
          const { result, rerender } = idleTimer()
          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(false)
          props.immediateEvents = ['mousedown']
          rerender()
          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(true)
        })

        it('Should memoize element', () => {
          props.events = ['keydown']
          props.immediateEvents = ['mousedown']
          props.timeout = 200
          props.startOnMount = false
          props.startManually = true
          props.onAction = jest.fn()
          props.eventsThrottle = 0
          const { result, rerender } = idleTimer()
          result.current.start()
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
          props.immediateEvents = ['mousedown']
          rerender(props)
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(2)
        })
      })

      describe('.timeout', () => {
        it('Should update timeout dynamically', async () => {
          props.onIdle = jest.fn()
          props.timeout = 200
          const { rerender, result } = idleTimer()

          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)

          props.timeout = 400
          rerender()

          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(600, 30)
          expect(props.onIdle).toHaveBeenCalledTimes(2)
        })

        it('Should call active on manager when timeout is updated', async () => {
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          props.timeout = 200
          props.crossTab = true
          const { rerender, result } = idleTimer()

          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)

          props.timeout = 400
          rerender()

          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(600, 30)
          expect(props.onIdle).toHaveBeenCalledTimes(2)
          expect(props.onActive).toHaveBeenCalledTimes(2)
        })

        it('Should update when started manually', async () => {
          props.timeout = 400
          props.startOnMount = false
          props.startManually = true
          props.stopOnIdle = true
          const { result, rerender } = idleTimer()
          result.current.pause()
          expect(result.current.isIdle()).toBe(true)
          props.timeout = 200
          rerender(props)
          result.current.start()
          expect(result.current.isIdle()).toBe(false)
          await sleep(200)
          expect(result.current.isIdle()).toBe(true)
        })

        it('Should call onActive if timeout changes while idle', async () => {
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          props.timeout = 200
          const { rerender, result } = idleTimer()

          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)

          props.timeout = 400
          rerender()

          await waitFor(() => result.current.isIdle())
          expect(props.onActive).toHaveBeenCalledTimes(1)
          expect(props.onIdle).toHaveBeenCalledTimes(2)
        })

        it('Should not call onActive if timeout changes while active', () => {
          props.onActive = jest.fn()
          props.timeout = 200

          const { rerender } = idleTimer()
          props.timeout = 400
          rerender()

          expect(props.onActive).toHaveBeenCalledTimes(0)
        })
      })

      describe('.promptTimeout', () => {
        it('Should call idle after prompt duration', async () => {
          props.timeout = 200
          props.promptTimeout = 200
          props.onPrompt = jest.fn()
          props.onIdle = jest.fn()

          const { result } = idleTimer()
          await sleep(200)
          expect(props.onPrompt).toHaveBeenCalledTimes(1)
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)
        })

        it('Should update dynamically', async () => {
          props.timeout = 200
          props.promptTimeout = 400
          props.onPrompt = jest.fn()
          props.onIdle = jest.fn()

          const { rerender } = idleTimer()
          props.promptTimeout = 200
          rerender()

          await sleep(200)
          expect(props.onPrompt).toHaveBeenCalledTimes(1)
          await sleep(200)
          expect(props.onIdle).toHaveBeenCalledTimes(1)
        })
      })

      describe('.startOnMount', () => {
        it('Should start immediately when set', () => {
          props.startOnMount = true
          const { result } = idleTimer()
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should not start when startOnMount not set', () => {
          props.startOnMount = false
          const { result } = idleTimer()
          expect(result.current.isIdle()).toBe(true)
        })

        it('Should start on first event', async () => {
          props.startOnMount = false
          props.onActive = jest.fn()
          const { result } = idleTimer()
          expect(props.onActive).toHaveBeenCalledTimes(0)
          expect(result.current.isIdle()).toBe(true)
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle() === false)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should update dynamically', async () => {
          props.timeout = 200
          props.startOnMount = false
          props.onIdle = jest.fn()
          props.onActive = jest.fn()

          const { result, rerender } = idleTimer()
          expect(result.current.isIdle()).toBe(true)
          expect(props.onIdle).toHaveBeenCalledTimes(0)
          expect(props.onActive).toHaveBeenCalledTimes(0)

          props.startOnMount = true
          rerender()

          expect(result.current.isIdle()).toBe(false)
          expect(props.onIdle).toHaveBeenCalledTimes(0)
          expect(props.onActive).toHaveBeenCalledTimes(0)

          result.current.start()
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)

          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })
      })

      describe('.startManually', () => {
        it('Should not start on activity when set', () => {
          props.timeout = 200
          props.startManually = true
          props.onIdle = jest.fn()
          props.onActive = jest.fn()

          const { result } = idleTimer()
          expect(result.current.isIdle()).toBe(true)
          fireEvent.mouseDown(document)

          expect(result.current.isIdle()).toBe(true)
          expect(props.onIdle).toHaveBeenCalledTimes(0)
          expect(props.onActive).toHaveBeenCalledTimes(0)
        })

        it('Should start when start() is called', async () => {
          props.timeout = 200
          props.startManually = true
          props.onIdle = jest.fn()
          props.onActive = jest.fn()

          const { result } = idleTimer()
          result.current.start()
          expect(result.current.isIdle()).toBe(false)

          // Wait for idle
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)
          expect(props.onActive).toHaveBeenCalledTimes(0)

          // Fire event
          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should update dynamically', async () => {
          props.timeout = 200
          props.startManually = false
          props.onIdle = jest.fn()
          props.onActive = jest.fn()

          const { result, rerender } = idleTimer()
          expect(result.current.isIdle()).toBe(false)
          expect(props.onIdle).toHaveBeenCalledTimes(0)
          expect(props.onActive).toHaveBeenCalledTimes(0)

          props.startManually = true
          rerender()

          expect(result.current.isIdle()).toBe(true)
          expect(props.onIdle).toHaveBeenCalledTimes(0)
          expect(props.onActive).toHaveBeenCalledTimes(0)

          result.current.start()
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)

          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })
      })

      describe('.stopOnIdle', () => {
        it('Should not restart on activity after idle', async () => {
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          props.timeout = 200
          props.stopOnIdle = true
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onIdle).toHaveBeenCalledTimes(1)
          expect(props.onActive).toHaveBeenCalledTimes(0)
          expect(result.current.isIdle()).toBe(true)
        })

        it('Should start on reset() when stopOnIdle is set', async () => {
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          props.timeout = 200
          props.stopOnIdle = true
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onIdle).toHaveBeenCalledTimes(1)
          expect(props.onActive).toHaveBeenCalledTimes(0)
          expect(result.current.isIdle()).toBe(true)
          result.current.reset()
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should go idle after reset() and user input when stopOnIdle is set', async () => {
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          props.timeout = 200
          props.stopOnIdle = true
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onIdle).toHaveBeenCalledTimes(1)
          expect(props.onActive).toHaveBeenCalledTimes(0)
          expect(result.current.isIdle()).toBe(true)
          result.current.reset()
          expect(result.current.isIdle()).toBe(false)
          expect(result.current.getRemainingTime()).toBeAround(props.timeout, 10)
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(2)
        })

        it('Should be able to be set dynamically', async () => {
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          props.timeout = 200
          props.stopOnIdle = false
          const { rerender, result } = idleTimer()

          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)

          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(false)
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(2)

          props.stopOnIdle = true
          rerender()

          expect(result.current.isIdle()).toBe(true)
          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(false)
          await waitFor(() => result.current.isIdle())

          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(true)
          expect(props.onActive).toHaveBeenCalledTimes(2)
        })

        it('Should unbind all events on idle when stopOnIdle is set', async () => {
          props.onAction = jest.fn()
          props.stopOnIdle = true
          props.timeout = 200

          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(0)
        })
      })

      describe('.onPrompt', () => {
        it('Should reset on start and reset', async () => {
          props.timeout = 200
          props.promptTimeout = 200
          props.onPrompt = jest.fn()
          props.onIdle = jest.fn()

          const { result } = idleTimer()
          await sleep(200)
          expect(props.onPrompt).toHaveBeenCalledTimes(1)
          await sleep(100)
          result.current.reset()
          await sleep(200)
          expect(props.onPrompt).toHaveBeenCalledTimes(2)
          result.current.start()
          await sleep(200)
          expect(props.onPrompt).toHaveBeenCalledTimes(3)
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)
        })

        it('Should update dynamically', async () => {
          props.timeout = 200
          props.promptTimeout = 200

          const fn1 = jest.fn()
          const fn2 = jest.fn()
          props.onPrompt = fn1

          const { result, rerender } = idleTimer()
          await sleep(200)
          expect(fn1).toHaveBeenCalledTimes(1)

          props.onPrompt = fn2
          rerender()
          result.current.reset()

          await sleep(200)
          expect(fn1).toHaveBeenCalledTimes(1)
          expect(fn2).toHaveBeenCalledTimes(1)
        })
      })

      describe('.onIdle', () => {
        it('Should call onIdle on user idle', async () => {
          props.onIdle = jest.fn()
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)
        })

        it('Should not call onIdle on larger timeouts', async () => {
          props.onIdle = jest.fn()
          props.timeout = 2147483647
          idleTimer()
          await sleep(100)
          expect(props.onIdle).toHaveBeenCalledTimes(0)
        })

        it('Should allow reassignment of onIdle', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()
          props.onIdle = fn1
          props.timeout = 200
          const { result, rerender } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(fn1).toHaveBeenCalledTimes(1)
          props.onIdle = fn2
          rerender()
          result.current.reset()
          await waitFor(() => result.current.isIdle())
          expect(fn2).toHaveBeenCalledTimes(1)
        })
      })

      describe('.onActive', () => {
        it('Should call onActive on user input when user is idle', async () => {
          props.onActive = jest.fn()
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should not call onActive on user input when user is not idle', async () => {
          props.onActive = jest.fn()
          props.timeout = 400
          idleTimer()
          await sleep(300)
          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(0)
        })

        it('Should allow reassignment of onActive', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()
          props.onActive = fn1
          props.timeout = 200
          const { result, rerender } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(fn1).toHaveBeenCalledTimes(1)
          props.onActive = fn2
          rerender()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(fn2).toHaveBeenCalledTimes(1)
        })
      })

      describe('.onAction', () => {
        it('Should call onAction on user input when user is not idle', async () => {
          props.onAction = jest.fn()
          props.eventsThrottle = 0
          idleTimer()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(2)
        })

        it('Should call onAction on user input when user is idle', async () => {
          props.onAction = jest.fn()
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })

        it('Should allow reassignment of onAction', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()
          props.onAction = fn1
          props.timeout = 200
          const { result, rerender } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(fn1).toHaveBeenCalledTimes(1)
          props.onAction = fn2
          rerender()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(fn2).toHaveBeenCalledTimes(1)
        })
      })

      describe('.onMessage', () => {
        it('Should not emit when emitOnSelf is not set', () => {
          props.onMessage = jest.fn()

          const { result } = idleTimer()
          const data = 'foo'
          result.current.message(data)

          expect(props.onMessage).toHaveBeenCalledTimes(0)
        })

        it('Should emit when emitOnSelf is set', () => {
          props.onMessage = jest.fn()

          const { result } = idleTimer()
          const data = 'foo'
          result.current.message(data, true)

          expect(props.onMessage).toHaveBeenCalledTimes(1)
          expect(props.onMessage).toHaveBeenCalledWith(data)
        })
      })

      describe('.debounce', () => {
        it('Should error if debounce and throttle are set', done => {
          jest.spyOn(console, 'error')
          props.debounce = 200
          props.throttle = 200
          const { result } = idleTimer()
          expect(result.error).toEqual(new Error('❌ onAction can either be throttled or debounced, not both.'))
          done()
        })

        it('Should debounce calls to onAction', async () => {
          props.onAction = jest.fn()
          props.debounce = 200
          props.eventsThrottle = 0
          idleTimer()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await sleep(200)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })

        it('Should cancel existing debounced function', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()
          props.onAction = fn1
          props.debounce = 200
          props.eventsThrottle = 0
          const { rerender } = idleTimer()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          props.onAction = fn2
          rerender(props)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await sleep(200)
          expect(fn1).toHaveBeenCalledTimes(0)
          expect(fn2).toHaveBeenCalledTimes(1)
        })

        it('Should cancel debounced callback on idle', async () => {
          props.onAction = jest.fn()
          props.timeout = 200
          props.debounce = 400
          props.eventsThrottle = 0
          const { result } = idleTimer()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          await sleep(300)
          expect(props.onAction).toHaveBeenCalledTimes(0)
        })

        it('Should dynamically update debounce', async () => {
          props.onAction = jest.fn()
          props.debounce = 400
          props.eventsThrottle = 0
          const { rerender } = idleTimer()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await sleep(400)
          expect(props.onAction).toHaveBeenCalledTimes(1)

          props.debounce = 200
          rerender()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await sleep(200)
          expect(props.onAction).toHaveBeenCalledTimes(2)
        })
      })

      describe('.throttle', () => {
        it('Should error if throttle and debounce are set', done => {
          jest.spyOn(console, 'error')
          props.throttle = 200
          props.debounce = 200
          const { result } = idleTimer()
          expect(result.error).toEqual(new Error('❌ onAction can either be throttled or debounced, not both.'))
          done()
        })

        it('Should throttle calls to onAction', async () => {
          props.onAction = jest.fn()
          props.throttle = 200
          props.eventsThrottle = 0
          idleTimer()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await sleep(200)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })

        it('Should dynamically update throttle', async () => {
          props.onAction = jest.fn()
          props.throttle = 400
          props.eventsThrottle = 0
          const { rerender } = idleTimer()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await sleep(400)
          expect(props.onAction).toHaveBeenCalledTimes(1)

          props.throttle = 200
          rerender()
          fireEvent.mouseDown(document)
          fireEvent.mouseDown(document)
          await sleep(200)
          expect(props.onAction).toHaveBeenCalledTimes(2)
        })
      })

      describe('.eventsThrottle', () => {
        it('Should not throttle events', async () => {
          props.eventsThrottle = 0
          props.timeout = 200
          props.onActive = jest.fn()
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(2)
        })

        it('Should throttle events', async () => {
          props.eventsThrottle = 1000
          props.timeout = 200
          props.onActive = jest.fn()
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should dynamically update eventsThrottle', async () => {
          props.eventsThrottle = 1000
          props.timeout = 200
          props.onActive = jest.fn()
          const { result, rerender } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(1)
          props.eventsThrottle = 100
          rerender()
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onActive).toHaveBeenCalledTimes(4)
        })
      })

      describe('.timers', () => {
        it('Should use custom timers', () => {
          const setTimeout = jest.fn()
          const clearTimeout = jest.fn()
          const setInterval = jest.fn()
          const clearInterval = jest.fn()
          props.timers = {
            setTimeout,
            clearTimeout,
            setInterval,
            clearInterval
          }
          idleTimer()
          expect(timers.setInterval).toEqual(setInterval)
          expect(timers.clearInterval).toEqual(clearInterval)
          expect(timers.setTimeout).toEqual(setTimeout)
          expect(timers.clearTimeout).toEqual(clearTimeout)

          // Rest timers
          createMocks()
        })
      })

      describe('.crossTab', () => {
        it('Should emit prompt, idle and active on manager', async () => {
          props.timeout = 200
          props.promptTimeout = 200
          props.startManually = true
          props.crossTab = true
          props.onPrompt = jest.fn()
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          const { result } = idleTimer()

          result.current.start()
          await waitFor(() => result.current.isIdle())

          expect(result.current.isIdle()).toBe(true)
          expect(props.onPrompt).toHaveBeenCalledTimes(1)
          expect(props.onIdle).toHaveBeenCalledTimes(1)

          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(false)
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should emit start, reset, pause and resume on manager', async () => {
          props.timeout = 200
          props.startManually = true
          props.crossTab = true
          props.onIdle = jest.fn()
          props.onActive = jest.fn()
          const { result } = idleTimer()

          result.current.start()
          await waitFor(() => result.current.isIdle())
          result.current.reset()
          result.current.start()

          await sleep(100)
          result.current.pause()

          expect(result.current.isIdle()).toBe(false)
          const remaining = result.current.getRemainingTime()
          expect(remaining).toBeAround(100, 20)

          result.current.resume()
          await sleep(remaining)

          expect(result.current.isIdle()).toBe(true)
          expect(props.onIdle).toHaveBeenCalledTimes(2)

          fireEvent.mouseDown(document)
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should update crossTab dynamically', async () => {
          props.timeout = 200
          props.crossTab = true
          props.onIdle = jest.fn()
          const { result, rerender } = idleTimer()
          await waitFor(() => result.current.isIdle())

          props.crossTab = false
          rerender()

          await waitFor(() => result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(1)
        })
      })

      describe('.name', () => {
        it('Should set separate names for multiple instances', async () => {
          props.timeout = 200
          props.crossTab = true
          props.name = 'timer-1'
          props.onIdle = jest.fn()
          props.crossTab = false
          const timer1 = idleTimer()

          props.name = 'timer-2'
          const timer2 = idleTimer()
          await waitFor(() => timer1.result.current.isIdle())
          await waitFor(() => timer2.result.current.isIdle())
          expect(props.onIdle).toHaveBeenCalledTimes(2)
        })
      })

      describe('.syncTimers', () => {
        it('Should keep timers relatively in sync', async () => {
          props.timeout = 500
          props.crossTab = true
          props.syncTimers = 200
          props.eventsThrottle = 0
          const { result } = idleTimer()
          const { result: result2 } = idleTimer()
          result.current.start()
          await sleep(100)
          fireEvent.mouseDown(document)
          await sleep(200)
          expect(result.current.getRemainingTime()).toBeAround(300, 20)
          expect(result2.current.getRemainingTime()).toBeAround(300, 20)
        })
      })
    })

    describe('.methods', () => {
      describe('.start()', () => {
        it('Should start timer when start is called', () => {
          props.startOnMount = false
          const { result } = idleTimer()
          result.current.start()
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should bind all events on start()', async () => {
          props.onAction = jest.fn()
          props.stopOnIdle = true
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(0)
          result.current.start()
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })

        it('Should not redefine on rerender', async () => {
          props.onAction = jest.fn()
          props.stopOnIdle = true
          props.timeout = 200
          const { result, rerender } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(0)
          rerender()
          result.current.start()
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })
      })

      describe('.reset()', () => {
        it('Should start timer when reset is called', () => {
          props.startOnMount = false
          const { result } = idleTimer()
          result.current.reset()
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should not start time when startManually is set', async () => {
          props.timeout = 200
          props.startOnMount = false
          props.startManually = true
          const { result } = idleTimer()
          result.current.reset()
          await sleep(200)
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should bind all events on reset()', async () => {
          props.onAction = jest.fn()
          props.stopOnIdle = true
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(0)
          result.current.reset()
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })
      })

      describe('.active()', () => {
        it('Should start timer when activate() is called', () => {
          props.startOnMount = false
          const { result } = idleTimer()
          result.current.activate()
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should call onActive if user was idle', async () => {
          props.timeout = 200
          props.onActive = jest.fn()
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          result.current.activate()
          expect(props.onActive).toHaveBeenCalledTimes(1)
        })

        it('Should emit active event when cross tab is enabled', async () => {
          props.timeout = 200
          props.onActive = jest.fn()
          props.crossTab = true
          const { result } = idleTimer()
          idleTimer()
          await waitFor(() => result.current.isIdle())
          result.current.activate()
          await sleep(100)
          expect(props.onActive).toHaveBeenCalledTimes(2)
        })

        it('Should bind all events on activate()', async () => {
          props.onAction = jest.fn()
          props.stopOnIdle = true
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(0)
          result.current.activate()
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })
      })

      describe('.pause()', () => {
        it('Should pause the timer', () => {
          const { result } = idleTimer()
          result.current.pause()
          expect(result.current.isIdle()).toBe(false)
        })

        it('Should not pause a paused idleTimer instance', () => {
          const { result } = idleTimer()
          result.current.pause()
          result.current.pause()
          expect(result.current.isIdle()).toBe(false)
          expect(result.current.getRemainingTime()).toBeDefined()
        })

        it('Should unbind all events on pause()', () => {
          props.onAction = jest.fn()
          props.timeout = 400
          const { result } = idleTimer()
          result.current.pause()
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(0)
        })

        it('Should have accurate remaining time', async () => {
          props.timeout = 400
          const { result } = idleTimer()
          await sleep(200)
          result.current.pause()
          const remaining = result.current.getRemainingTime()
          expect(remaining).toBeAround(200, 10)
          await sleep(200)
          expect(result.current.getRemainingTime()).toBe(remaining)
        })
      })

      describe('.resume()', () => {
        it('Should resume a paused idleTimer instance', async () => {
          props.timeout = 400
          const { result } = idleTimer()
          await sleep(200)
          result.current.pause()
          expect(result.current.isIdle()).toBe(false)
          result.current.resume()
          await waitFor(() => result.current.isIdle())
        })

        it('Should not resume a running idleTimer instance', async () => {
          props.timeout = 400
          const { result } = idleTimer()
          await sleep(200)
          result.current.resume()
          expect(result.current.getRemainingTime()).toBeLessThanOrEqual(props.timeout)
        })

        it('Should bind all events on resume()', () => {
          props.onAction = jest.fn()
          props.timeout = 400
          const { result } = idleTimer()
          result.current.pause()
          fireEvent.mouseDown(document)
          expect(props.onAction).toBeCalledTimes(0)
          result.current.resume()
          fireEvent.mouseDown(document)
          expect(props.onAction).toBeCalledTimes(1)
        })

        it('Should resume from paused time', async () => {
          props.timeout = 400
          const { result } = idleTimer()
          await sleep(200)
          result.current.pause()
          expect(result.current.isIdle()).toBe(false)
          expect(result.current.getRemainingTime()).toBeAround(200, 10)
          result.current.resume()
          await sleep(100)
          expect(result.current.isIdle()).toBe(false)
          await sleep(101)
          expect(result.current.isIdle()).toBe(true)
        })

        it('Should have accurate remaining time', async () => {
          props.timeout = 400
          const { result } = idleTimer()
          await sleep(200)
          result.current.pause()
          const remaining = result.current.getRemainingTime()
          expect(remaining).toBeAround(200, 10)
          result.current.resume()
          expect(result.current.getRemainingTime()).toBeAround(remaining, 10)
          await sleep(100)
          expect(result.current.getRemainingTime()).toBeAround(remaining - 100, 10)
        })

        it('Should not rebind events while prompt is active', async () => {
          props.timeout = 200
          props.promptTimeout = 400
          props.onActive = jest.fn()
          const { result } = idleTimer()
          await waitFor(() => result.current.isPrompted())
          await sleep(100)
          result.current.pause()
          await sleep(100)
          result.current.resume()
          fireEvent.mouseDown(document)
          expect(result.current.isPrompted()).toBe(true)
          expect(props.onActive).toHaveBeenCalledTimes(0)
        })
      })

      describe('.message()', () => {
        it('Should send message across tabs when crossTab is enabled', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()

          props.onMessage = fn1
          props.crossTab = true

          const idleTimer1 = idleTimer()

          props.onMessage = fn2
          idleTimer()

          const data = 'foo'
          idleTimer1.result.current.message(data)

          await waitFor(() => fn2.mock.calls.length === 1)
          expect(fn1).toHaveBeenCalledTimes(0)
          expect(fn2).toHaveBeenCalledTimes(1)
          expect(fn2).toHaveBeenCalledWith(data)
        })

        it('Should emit on local callee instance when emitOnSelf is true', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()

          props.onMessage = fn1
          props.crossTab = true

          const idleTimer1 = idleTimer()

          props.onMessage = fn2
          idleTimer()

          const data = 'foo'
          idleTimer1.result.current.message(data, true)

          await waitFor(() => fn2.mock.calls.length === 1)
          expect(fn1).toHaveBeenCalledTimes(1)
          expect(fn1).toHaveBeenCalledWith(data)
          expect(fn2).toHaveBeenCalledTimes(1)
          expect(fn2).toHaveBeenCalledWith(data)
        })

        it('Should accept string data', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()

          props.onMessage = fn1
          props.crossTab = true

          const idleTimer1 = idleTimer()

          props.onMessage = fn2
          idleTimer()

          const data = 'foo'
          idleTimer1.result.current.message(data, true)

          await waitFor(() => fn2.mock.calls.length === 1)
          expect(fn1).toHaveBeenCalledTimes(1)
          expect(fn1).toHaveBeenCalledWith(data)
          expect(fn2).toHaveBeenCalledTimes(1)
          expect(fn2).toHaveBeenCalledWith(data)
        })

        it('Should accept object data', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()

          props.onMessage = fn1
          props.crossTab = true

          const idleTimer1 = idleTimer()

          props.onMessage = fn2
          idleTimer()

          const data = { foo: 'bar' }
          idleTimer1.result.current.message(data, true)

          await waitFor(() => fn2.mock.calls.length === 1)
          expect(fn1).toHaveBeenCalledTimes(1)
          expect(fn1).toHaveBeenCalledWith(data)
          expect(fn2).toHaveBeenCalledTimes(1)
          expect(fn2).toHaveBeenCalledWith(data)
        })

        it('Should accept number data', async () => {
          const fn1 = jest.fn()
          const fn2 = jest.fn()

          props.onMessage = fn1
          props.crossTab = true

          const idleTimer1 = idleTimer()

          props.onMessage = fn2
          idleTimer()

          const data = 1337
          idleTimer1.result.current.message(data, true)

          await waitFor(() => fn2.mock.calls.length === 1)
          expect(fn1).toHaveBeenCalledTimes(1)
          expect(fn1).toHaveBeenCalledWith(data)
          expect(fn2).toHaveBeenCalledTimes(1)
          expect(fn2).toHaveBeenCalledWith(data)
        })
      })

      describe('.isIdle()', () => {
        it('Should get the idle state', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          expect(result.current.isIdle()).toBe(false)
          await waitFor(() => result.current.isIdle())
          expect(result.current.isIdle()).toBe(true)
        })
      })

      describe('.isPrompted', () => {
        it('Should return false when promptTimeout is not set', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          expect(result.current.isPrompted()).toBe(false)
        })

        it('Should return true after timeout when promptTimeout is set', async () => {
          props.timeout = 200
          props.promptTimeout = 400
          const { result } = idleTimer()
          await sleep(200)
          expect(result.current.isPrompted()).toBe(true)
        })

        it('Should emit onAction while prompt is active', async () => {
          props.timeout = 200
          props.promptTimeout = 400
          props.onAction = jest.fn()
          const { result } = idleTimer()
          await sleep(200)
          expect(result.current.isPrompted()).toBe(true)
          fireEvent.mouseDown(document)
          expect(props.onAction).toHaveBeenCalledTimes(1)
        })
      })

      describe('.isLeader', () => {
        it('Should throw error when crossTab is not set', async () => {
          props.crossTab = false
          const { result } = idleTimer()
          expect(() => result.current.isLeader()).toThrow(
            new Error('❌ Cross Tab feature is not enabled. To enable it set the "crossTab" property to true.')
          )
        })

        it('Should throw error when leaderElection is not set', async () => {
          props.crossTab = true
          const { result } = idleTimer()
          expect(() => result.current.isLeader()).toThrowError(
            '❌ Leader election is not enabled. To Enable it set the "leaderElection" property to true.'
          )
        })

        it('Should return boolean when properly set up', async () => {
          props.timeout = 200
          props.crossTab = true
          props.leaderElection = true
          const { result } = idleTimer()
          expect(result.current.isLeader()).toBe(false)
          await waitFor(() => result.current.isLeader(), { timeout: 3000 })
          expect(result.current.isLeader()).toBe(true)
        })
      })

      describe('.getTabId', () => {
        it('Should throw when crossTab is not enabled', () => {
          const { result } = idleTimer()
          expect(() => result.current.getTabId()).toThrow(
            new Error('❌ Cross Tab feature is not enabled. To enable it set the "crossTab" property to true.')
          )
        })

        it('Should return unique ids', () => {
          props.crossTab = true
          const timer1 = idleTimer()
          const timer2 = idleTimer()
          expect(timer1.result.current.getTabId()).not.toBe(timer2.result.current.getTabId())
        })

        it('Should generate unique ids for many instances', () => {
          props.crossTab = true
          const ids = []
          for (let i = 0; i < 100; i++) {
            const { result } = idleTimer()
            ids.push(result.current.getTabId())
          }
          expect((new Set(ids)).size).toBe(ids.length)
        })
      })

      describe('.getRemainingTime()', () => {
        it('Should return 0 for remaining time while idle', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          expect(result.current.getRemainingTime()).toBe(0)
        })

        it('Should return remaining time while paused', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          await sleep(100)
          result.current.pause()
          expect(result.current.getRemainingTime()).toBeAround(100, 10)
        })

        it('Should return timeout value when not started', async () => {
          props.timeout = 400
          props.startManually = true
          const { result } = idleTimer()
          expect(result.current.getRemainingTime()).toBe(props.timeout)
          result.current.start()
          await waitFor(() => result.current.isIdle())
          expect(result.current.getRemainingTime()).toBe(0)
        })

        it('Should recalculate when timeout is changed', async () => {
          props.timeout = 400
          props.startManually = true
          const { result, rerender } = idleTimer()
          expect(result.current.getRemainingTime()).toBe(props.timeout)
          props.timeout = 800
          rerender()
          expect(result.current.getRemainingTime()).toBe(props.timeout)
        })

        it('Should return prompt remaining time when prompt is active', async () => {
          props.timeout = 200
          props.promptTimeout = 400
          props.onPrompt = jest.fn()

          const { result } = idleTimer()
          await sleep(100)
          expect(result.current.getRemainingTime()).toBeAround(500, 10)

          await waitFor(() => result.current.isPrompted())
          expect(props.onPrompt).toHaveBeenCalledTimes(1)
          await sleep(100)
          expect(result.current.getRemainingTime()).toBeAround(300, 15)
        })

        it('Should return correct value when paused and resumed', async () => {
          props.timeout = 200
          props.onPrompt = jest.fn()

          const { result } = idleTimer()
          await sleep(100)
          result.current.pause()
          expect(result.current.getRemainingTime()).toBeAround(100, 10)
          await sleep(200)
          result.current.resume()
          expect(result.current.getRemainingTime()).toBeAround(100, 10)

          await waitFor(() => result.current.isIdle())
          expect(result.current.getRemainingTime()).toBeAround(0, 5)
        })

        it('Should return correct value when paused and resumed while prompted', async () => {
          props.timeout = 200
          props.promptTimeout = 400
          props.onPrompt = jest.fn()

          const { result } = idleTimer()
          await waitFor(() => result.current.isPrompted())
          result.current.pause()
          expect(result.current.getRemainingTime()).toBeAround(props.promptTimeout, 20)
          await sleep(100)
          expect(result.current.getRemainingTime()).toBeAround(props.promptTimeout, 20)
          result.current.resume()
          expect(result.current.getRemainingTime()).toBeAround(props.promptTimeout, 20)
          await sleep(100)
          expect(result.current.getRemainingTime()).toBeAround(props.promptTimeout - 100, 20)
          result.current.pause()
          await sleep(100)
          result.current.resume()
          await waitFor(() => result.current.isIdle())
          expect(result.current.getRemainingTime()).toBe(0)
        })

        it('Should reset when start, reset or activate is called', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          await sleep(100)
          expect(result.current.getRemainingTime()).toBeAround(100, 10)
          await waitFor(() => result.current.isIdle())
          expect(result.current.getRemainingTime()).toBe(0)
          result.current.reset()
          expect(result.current.getRemainingTime()).toBeAround(200, 10)
          await waitFor(() => result.current.isIdle())
          expect(result.current.getRemainingTime()).toBe(0)
          result.current.start()
          expect(result.current.getRemainingTime()).toBeAround(200, 10)
          await waitFor(() => result.current.isIdle())
          expect(result.current.getRemainingTime()).toBe(0)
          result.current.activate()
          expect(result.current.getRemainingTime()).toBeAround(200, 10)
        })
      })

      describe('.getElapsedTime()', () => {
        it('Should get the elapsed time', async () => {
          const { result } = idleTimer()
          await sleep(200)
          expect(result.current.getElapsedTime()).toBeAround(200, 20)
          await sleep(200)
          expect(result.current.getElapsedTime()).toBeAround(400, 20)
        })

        it('Should reset when reset() is called', async () => {
          const { result } = idleTimer()
          await sleep(200)
          expect(result.current.getElapsedTime()).toBeAround(200, 20)
          await sleep(200)
          expect(result.current.getElapsedTime()).toBeAround(400, 20)
          result.current.reset()
          expect(result.current.getElapsedTime()).toBeAround(0, 10)
        })
      })

      describe('.getTotalElapsedTime()', () => {
        it('Should get the elapsed time', async () => {
          const { result } = idleTimer()
          await sleep(200)
          expect(result.current.getTotalElapsedTime()).toBeAround(200, 20)
          await sleep(200)
          expect(result.current.getTotalElapsedTime()).toBeAround(400, 20)
        })
      })

      describe('.getLastIdleTime()', () => {
        it('Should get the last idle time', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          expect(result.current.getLastIdleTime().getTime()).toBeAround(Date.now(), 20)
        })

        it('Should return null if has not been idle', () => {
          props.startManually = true
          const { result } = idleTimer()
          expect(result.current.getLastIdleTime()).toBe(null)
        })

        it('Should recalculate when lastIdle changes', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          expect(result.current.getLastIdleTime().getTime()).toBeAround(Date.now(), 20)
        })
      })

      describe('.getTotalIdleTime()', () => {
        it('Should get the total idle time', async () => {
          props.timeout = 200
          const { result } = idleTimer()

          await sleep(300)
          expect(result.current.getTotalIdleTime()).toBeAround(100, 10)
          fireEvent.mouseDown(document)

          await sleep(100)
          expect(result.current.getTotalIdleTime()).toBeAround(100, 15)

          await sleep(300)
          expect(result.current.getTotalIdleTime()).toBeAround(300, 20)
        })

        it('Should return 0 when it has not been idle', async () => {
          props.timeout = 200
          props.startManually = false
          const { result } = idleTimer()
          expect(result.current.getTotalIdleTime()).toBe(0)
          result.current.start()
          expect(result.current.getTotalIdleTime()).toBe(0)
        })

        it('Should recalculate when lastIdle changes', async () => {
          props.timeout = 200
          const { result } = idleTimer()

          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalIdleTime()).toBeAround(0, 20)

          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          await sleep(200)
          expect(result.current.getTotalIdleTime()).toBeAround(200, 30)
        })
      })

      describe('.getLastActiveTime()', () => {
        it('Should get the last active time', async () => {
          props.timeout = 200
          props.startManually = true
          const { result } = idleTimer()
          result.current.start()
          expect(result.current.getLastActiveTime().getTime()).toBeAround(Date.now(), 20)
        })

        it('Should return null if has not been active', () => {
          props.startManually = true
          const { result } = idleTimer()
          expect(result.current.getLastActiveTime()).toBe(null)
        })

        it('Should recalculate when lastActive changes', async () => {
          props.timeout = 200
          const { result } = idleTimer()
          await waitFor(() => result.current.isIdle())
          fireEvent.mouseDown(document)
          expect(result.current.getLastActiveTime().getTime()).toBeAround(Date.now(), 20)
        })
      })

      describe('.getTotalActiveTime()', () => {
        it('Should get the total active time', async () => {
          props.timeout = 300
          const { result } = idleTimer()

          // Test during active
          await sleep(100)
          expect(result.current.getTotalActiveTime()).toBeAround(100, 20)

          // Test after idle
          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(300, 25)

          // Activate
          fireEvent.mouseDown(document)
          await sleep(100)

          fireEvent.mouseDown(document)
          await sleep(100)

          fireEvent.mouseDown(document)
          await sleep(100)

          expect(result.current.getTotalActiveTime()).toBeAround(600, 20)
        })

        it('Should return 0 when it has not been active', async () => {
          props.timeout = 200
          props.startManually = true
          const { result } = idleTimer()
          expect(result.current.getTotalActiveTime()).toBe(0)
          result.current.start()
          expect(result.current.getTotalActiveTime()).toBeAround(0, 20)
          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(200, 20)
        })

        it('Should recalculate when lastActive changes', async () => {
          props.timeout = 200
          const { result } = idleTimer()

          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(200, 20)

          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(400, 20)
        })

        it('Should start over when reset is called', async () => {
          props.timeout = 200
          const { result } = idleTimer()

          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(200, 20)

          fireEvent.mouseDown(document)
          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(400, 20)

          result.current.reset()
          await waitFor(() => result.current.isIdle())
          expect(result.current.getTotalActiveTime()).toBeAround(200, 20)
        })
      })
    })
  })
})

redpajama_set_name: RedPajamaGithub


Mobile-first investment platform Stash is about to go mobile-first in the field of online banking, reports David Penn at Finovate (Banking Technology's sister company).
The New York-based start-up, which demonstrated its Stash Retire solution at its Finovate debut last month at FinovateFall 2017, plans to offer a variety of banking services for mobile-centric customers.
The services, bundled as Stash Banking and slated to be available in early 2018, include common banking solutions such as billpay, direct deposit, and debit cards. The platform has a goals-based savings feature, with auto and smart-save functionality as well as access to Stash's proprietary long-term financial security strategy, The Stash Plan. Accounts with Stash Banking are free, FDIC-insured, with no fees, no minimum balance requirement and are accessible via the largest ATM network in the US.
Stash was founded in 2015. Stash Retire gives investors the opportunity to participate in low-fee, self-directed IRA accounts while still taking advantage of Stash Invest's core features such as auto-invest and the ability to invest in increments as small as $5.
With more than 2.5 million subscribers and more than one million clients, Stash has raised more than $78 million in funding, including a $40 million Series C completed this summer. The company includes Breyer Capital, Coatue Management, Goodwater Capital, and Valar Ventures among its investors.
Brazilian fintech Nubank will soon be offering digital banking accounts in addition to its credit card business. The move will provide access to billpay, account-to-account transfers, and the ability to earn more in interest than is available with a regular savings account.
Welcomes three new faces - investment service Wahed, BitArabia and online Bitcoin exchange Belfrics.


Virginia@: Message from Bear Witness - BREAKING!
As a student at Harvard Law School, then-bachelor Barack Obama's practice of wearing a gold band on his wedding-ring finger puzzled his colleagues. Now, newly published photographs of Obama from the 1980s show that the ring Obama wore on his wedding-ring finger as an unmarried student is the same ring Michelle Robinson put on his finger at the couple's wedding ceremony in 1992. Moreover, according to Arabic-language and Islamic experts, the ring Obama has been wearing for more than 30 years is adorned with the first part of the Islamic declaration of faith, the Shahada: "There is no god except Allah." The Shahada is the first of the Five Pillars of Islam, expressing the two fundamental beliefs that make a person a Muslim: There is no god but Allah, and Muhammad is Allah's prophet. Sincere recitation of the Shahada is the sole requirement for becoming a Muslim, as it expresses a person's rejection of all other gods.
CAN IT ALL BE A COINCIDENCE? WOW!!
At the age of seventeen I invaded Cuba at the Bay of Pigs, in an effort to eradicate communism in the country of my birth. We lost the battle due to the failure of the Kennedy administration in 1961 to follow through on the original plan prepared by the Joint Chiefs of Staff and the Central Intelligence Agency. It was an act of criminal negligence. The 1176 prisoners of war of the Brigade 2506 were sentenced to 30 years in prison at hard labor. After two horrendous years of imprisonment, we were released after successful negotiations between the United States and Cuba.


What's the best #Mastodon app for #iOS? I splashed out on #Mast but it's pretty buggy.
hey so!!! are you asking a specific question online and not getting any help?
Never been prouder of my vicar than today.
St. Mary the Virgin will be open to all faiths and none tomorrow, 10am to 12noon for individual solace, prayer and the lighting of candles following today's tragedy.
Noticed a surge of activity on pixelfed.social since the mobile UI updates!
it's time to pull out the complete discography by The Prodigy and play it from start to finish!
They influenced me immensely and the whole generation of breakbeat producers and rave-goers.
... Oh god I'm old...!
A visualization of the terms of service for your popular web service.


Last August (which feels like an eternity ago, to be honest), I blogged about Dan's solo flight in the T-6. He has now soloed in the T-38 and is well on his way to completely pilot training at ENJJPT (Euro-Nato Joint Jet Pilot Training) at Sheppard Air Force Base. He's such a stud, and I am SO proud of him. He is putting in a lot of hard work and long days, but it's all for the best for him and our family, and one day, when this is all over with, it will be worth it!
Unfortunately for his solo, no one was available to take Annabelle and me out to the flight line like we were able to for his T-6 solo. Everyone was busy flying at the same time that day, so it just didn't work out. But I made sure he snapped a photo afterward anyway!
The T-38 is a lot faster (and more fun, according to Dan) than the T-6. He has been having a blast flying it. Since his solo, he has also passed his first check ride! More to come, though!
Pilot training certainly isn't for the faint of heart. And I can definitely see why there are so few married student pilots and even fewer with children. Dan is gone ALL DAY five days a week. He gets to see Annabelle for about an hour a day ON GOOD DAYS. We're sacrificing so much time with him right now, and the single parenting gig isn't easy. BUT we try to make up for it on the weekends. Annie is SO excited when she gets to see him and play with him.
Since many people have asked what drop night is, I'll give a quick run-down. Basically, all of the student pilots in one class (about 25) will receive their assignments (aka what plane they'll be flying for their Air Force careers, along with their first base) in a public setting on base on a Friday night. Drop nights happen every six weeks at Sheppard, and they're SO much fun. One at a time, the student pilots take turns standing up in front of everyone and learning their entire future right along with the hundred of people filling the room. It's exhilarating, nerve-racking, and crazy all at once. There's free beer involved and lots of screaming! It's a really fun tradition... but just know that my own husband is the one in the hot seat, I'm going to be one big ball of nerves. He has just under 11 weeks to go until it's his drop night! Only one more takes place before his. AAHHHH!
I know, I know. I'm WAY behind again. Blogging just hasn't sounded enjoyable lately for whatever reason. But I know deep down that I want to document our lives (especially Annabelle updates!) so we can read back over them someday.
That's why I am sharing her 18 month update today completely out of the blue. I haven't posted in over a month, and then I show up just to talk about my child. Typical, right? Ha - sorry!
Annabelle has grown quite a bit since her last update at 15 months old - she is now 33 inches tall and weighs 22 pounds! She is tall and skinny, just like her mama used to be. Now, I'm just tall... and not so skinny. She now has 14 teeth (okay, actually 15, as another one has popped up since her actual half birthday), and she is as feisty as ever - and we LOVE it!
Since her last update in December, Annabelle has traveled to Kansas City and Joplin to celebrate Christmas, San Antonio for her dad's centrifuge training, and Dallas for another wedding (Nate and Margot). She went to the San Antonio Zoo (her 4th zoo!) and has exploded with words! Her vocabulary grows daily, and right now, she's up to about 30 words she uses pretty regularly (but not always on demand).
Annabelle still runs constantly - she is nonstop motion. She is still obsessed with all things duck and Daniel Tiger, and she is really starting to love owls as well. She can count to three, and she is wearing mostly 12 and 18 month clothing.
It is such a privilege being Annabelle's mama. She is ornery and stubborn, but she has such a big heart as well. She loved fiercely, and she gives the best hugs and kisses. She is my little shadow, and I wouldn't have it any other way!
Next Annabelle update will be her 21 month update in June! How?! HOW?! My girl is growing up way too quickly.


When God blesses you financially, don't raise your standard of living, raise your standard of Giving!
These are some beautiful quotes to read when you are depressed, sad or just need a little bit of motivation! Love yourself, read them, raise and shine!
Patience with family is love, patience with others is respect, patience with sad is confidence and patience with God is faith.
This is truly my prayer Father God!
God quotes: learn lessons…trying to figure this out!
We can't fathom how big God is, yet He cares for each one of us and hears our prayers.
Surrender to God for he runs the agenda, only then will happiness blossom! Believe and trust in the Lord the most powerful!
When God sees you doing your part, developing what He has given you, then He will do His part and open doors that no man can shut.
But it's alright because one day it won't be that way.
God is Everything for Us !!
Positive Inspirational Quotes: A bad attitude is like a flat tire.
if you cant get someone out of your head love love quotes relationships cute quote couple heart hands love quote true love Like this.


The newly passed gambling legislation in Switzerland, the Swiss Gaming Act, will come into force in the country on 1 January 2019. The law will regulate the licensed online gambling space and ban foreign operators altogether.
The new law legalises licensed iGaming companies.
The gaming act's enforcement was confirmed by Switzerland's Federal Council, which confirmed its implementation starting next January. It also explained it will consider licence applications during the first six months of 2019, in compliance with the new legislation, and the first ones are set to be issued before July 1, when the foreigner's ban comes into effect as well.
Licensed operators can provide poker and roulette games to the customers, but need to stick with stringent constraints about the stakes.
The "concrete measures" of the new legislation were aimed to protect problem gamblers.


text:
Page B3.2 . 02 March 2011
Reskinning
Re-Skinning Awards
Design for Flooding
Design and enhancement of the water balance and resources of watersheds, aquifers, floodplains, and built infrastructure can mitigate and help to prepare for severe weather and climate change.
Flooding can benefit a region if it is anticipated. Rain collection from both intermittent and storm flooding of natural areas serves to replenish and stabilize the vegetative soil layer, and cleanses areas susceptible to salinity. Plentiful rain moving across the land and stored in groundwater aquifers provides inland waterways for wildlife habitat and for countless human purposes, including food, fire safety, recreation, and freshwater essential to all of life.
We present a new approach for designing buildings and communities, with five defining concepts.
Design for Resilience
Resilient design prepares for extreme storms and flooding of inland watersheds and coastal areas to provide resiliency and emergency preparedness for natural disaster. The concept of resiliency applies lessons from natural systems to design for extreme conditions using strategies of buffering, zone separation, redundancy, rapid feedback, and decentralization. Resilient design presents a new paradigm for design and building professionals to create buildings, communities, and regions that restore and improve our water resources and that mitigate threats of extreme weather and climate change.
Protect and Extend Ecosystem Services
The concept of ecosystem services recognizes and helps to credit the economic, health, and social benefits derived from functioning natural environments — land, vegetation, water, and living organisms. Natural landscapes provide clean air, freshwater storage, diversity of plants and wildlife, crop pollination, groundwater recharge, waste decomposition, and recycling of nutrients. Forests provide greenhouse gas mitigation and regenerative response to fire, drought, flooding, and climate change. Wetlands control erosion and flooding, remove pollutants from water, and recharge the groundwater reservoirs that we all rely on for our water supply. Coastal marshes, wetlands, and mangroves provide important buffers to coastal storms and storm surge.
Create Watershed Plans and Sustainable Stormwater Systems
Watershed planning is a multidisciplinary approach to water as a valued resource considered at each phase of its flow and use within natural systems defined by specific geological and climatic conditions. This concept focuses on water flows within the natural systems of regions, including restoration of the subsurface aquifers and integration of water and green infrastructure in urban development.
Sustainable stormwater design is an approach that reduces disturbance, protects and restores natural features, and uses soil and vegetation to manage stormwater. The focus of this concept is on designs that improve the local and regional water balance as a resource and principal element of flood-control engineering.
Implement Floodplain Management and Flood-Resistant Design
Floodplain management is a correlate and extension of watershed planning adopted into practice, focusing on the impacts of flooding. It includes land use policies and regulations for development in flood-prone areas, restoration and protection of natural resources and functions of floodplains and contributing watersheds, and flood-resistant design. New "smart grid" techniques allow automatic monitoring and rapid response to river flooding as well as monitoring dikes and other flood-control measures.
Flood-resistant design includes avoidance by relocating buildings and infrastructure out of harm's way, along with flood protection and mitigation measures: raising buildings above code-mandated flood levels, engineering buildings for severe wind and wave impacts, and using materials that are waterproof or otherwise impermeable to water damage.
Practice the Precautionary Principle
Designing to code minimum is not sufficient as a professional and due-diligent response to flooding and other increasingly severe impacts of extreme weather and climate change. The way we have built on the land — meeting only the minimum regulatory requirements under present law — has made things worse.
Following current planning to code minimums in many cases aggravates flooding beyond the project boundaries by fragmenting natural areas, increasing hardscape that increases storm overflows, and eliminating open space and vegetation that historically have served as natural filters and buffers. At the same time, increasingly severe weather events are exceeding guidelines and regulatory minimums represented in codes, which are slow to respond to new information and need for higher standards.
The design of buildings, especially in areas exposed to flooding, involves risk assessment by designers and building owners. Risk assessment requires decisions that must somehow mediate between options, some riskier than others, some costlier than others, some more difficult to implement. Design is a response to risk in the charge to provide shelter and habitable spaces and livable communities, fulfilling the broadly defined obligation to the public to protect life, safety, and welfare.
The precautionary principle considers that if an action or policy might cause severe or irreversible harm to public health or the environment, restraint is called for, and, in the absence of verifiable documentation that harm will not result, either to not undertake the action or to require consideration of all feasible and less risky alternatives.
The precautionary approach is defined in the 1992 Rio Earth Summit Declaration:
In order to protect the environment, the precautionary approach shall be widely applied by States according to their capabilities. Where there are threats of serious or irreversible damage, lack of full scientific certainty shall not be used as a reason for postponing cost-effective measures to prevent environmental degradation.
The precautionary principle is a response to risk of possible or probable harm to health or environment, even if the extent of harm is not yet fully established or documented. It is an ethical principle. When adopted as a guideline for public policy and where there is credible evidence of potential harm if an action is taken, then immediate steps must be considered to mitigate, reduce, or eliminate that threat while also pursuing risk assessment studies.
The precautionary principle is properly applied to actions that are potentially irreversible, such as planning where biodiversity and ecological services may be irretrievably lost or reduced. The principle suggests that "interventions must be reversible and flexible. Any mistakes must be correctible."*
* Ticknor, Joel, Carolyn Raffensperger, and Nancy Myers. The Precautionary Principle in Action: A Handbook. Science and Environmental Health Network, 1997. >>>
Donald Watson, FAIA, an architect and planner, is former chair of the Yale School of Architecture's Environmental Design Program, and former professor and dean of the School of Architecture at Rensselaer Polytechnic Institute. He received the 2002 ACSA Distinguished Professor Award and the 2005 AARC Haecker Leadership Award for Architectural Research. His publications include Climatic Building Design, winner in the "architecture and urban planning" category of the American Publishers Award for Professional and Scholarly Excellence.
Michele Adams, P.E., a water resources engineer, is principal and founder of Meliora Environmental Design in Kimberton, Pennsylvania. Her work encompasses environmentally sensitive site design and sustainable water resources engineering.
This article is excerpted from Design for Flooding by Donald Watson and Michele Adams, copyright © 2011, with permission of the publisher, John Wiley & Sons.
Weeks of extremely heavy rains in late December 2010 and early January 2011 led to massive flooding across eastern Australia in the states of Queensland, New South Wales, and Victoria. This NASA satellite photo from January 9 shows flooding of the Fitzroy River in Rockhampton, Queensland, a city of about 75,000 residents. Image does not appear in book.
Photo: NASA Extra Large Image
Flooded houses in St. Bernard Parish, Louisiana, about a week after Hurricane Katrina devastated parts of the U.S. Gulf Coast in 2005.
Photo: Michael Rieger/ FEMA Extra Large Image
A debris staging area in the Lakeview area of New Orleans, July 2008. Some 58.8 million cubic yards (45 million cubic meters) of debris had been collected in Louisiana by that time, following Hurricanes Katrina and Rita.
Photo: Andrea Booher/ FEMA Extra Large Image
Impervious surfaces such as pavement, roofs, and landscaping can transform nearly all precipitation into runoff, as illustrated in this sample precipitation diagram for the Philadelphia, Pennsylvania, region.
Image: John Wiley & Sons Extra Large Image
In contrast, a natural landscape in the Philadelphia region returns most precipitation to the atmosphere through evapotranspiration, resulting in comparatively little runoff.
Image: Wiley Extra Large Image
Diagram illustrating the global carbon cycle. Where known, the mass of each carbon sink and process is indicated in gigatons of carbon (Gt C).
Clouds form when warm thermal updrafts encounter cooler air at higher altitudes, causing moisture in the warm air to condense.
Photo: © Reg Morrison Extra Large Image
Design for Flooding: Architecture, Landscape, and Urban Design for Resilience to Climate Change by Donald Watson and Michele Adams.
Image: Wiley


I have just come across a tab I've not seen before and cannot find it in my manuals.
I think it's an obselete tag.
Elements (like div and a) have starting and ending tags, and starting tags can contain attributes.
As for the status of tppabs, it has never existed. It's inserted into markup by Teleport Pro (http://www.tenmax.com/teleport/pro/home.htm) and contains the absolute form of a URL. This allows the software to locate a resource once the document has been downloaded. It serves no purpose as far as HTML is concerned.