Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1426096
integration.test.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
integration.test.js
View Options
import
*
as
Redux
from
'redux'
;
import
*
as
ReduxThunk
from
'redux-thunk'
;
import
*
as
WaitModule
from
'../../src/wait'
;
import
*
as
stubs
from
'./stubs'
;
import
*
as
actions
from
'../../src/actions'
;
import
reducers
from
'../../src/reducers'
;
import
registerChangeListener
from
'../../src/changeListener'
;
import
{
previewTypes
}
from
'../../src/preview/model'
;
/**
* Whether Gateway#fetchPreviewForTitle is resolved or rejected.
*
* @enum {number}
*/
const
FETCH_RESOLUTION
=
{
RESOLVE
:
0
,
REJECT
:
1
};
function
identity
(
x
)
{
return
x
;
}
function
constant
(
x
)
{
return
()
=>
x
;
}
/*
* Integration tests for actions and state of the preview part of the system.
* Follows a diagram of the interactions considered valid, which will be
* used as a basis for the following tests:
*
+--------+
|INACTIVE+-----------------------+
+---+----+ |
^ |
| link or preview |
| abandon end |
| link_dwell|
| |
| |
| |
+---|----------------------------|---+
| | ACTIVE | |
+---|----------------------------|---+
| + v |
| OFF_LINK ON_LINK | Inside ACTIVE, or out
| + ^ link or preview | ^ | of it, only actions with
| | | abandon start | | | that same active link are
| | +----------------------+ | | valid. Others are ignored.
| | | |
| +----------------------------+ |
| preview or same link dwell |
| |
| NO_DATA +-------> DATA |
| fetch end |
+------------------------------------+
*/
QUnit
.
module
(
'ext.popups preview @integration'
,
{
beforeEach
()
{
// The worst-case implementation of mw.now.
mw
.
now
=
()
=>
Date
.
now
();
this
.
resetWait
=
()
=>
{
this
.
waitDeferred
=
$
.
Deferred
();
this
.
waitPromise
=
this
.
waitDeferred
.
promise
();
this
.
wait
.
returns
(
this
.
waitPromise
);
};
this
.
wait
=
this
.
sandbox
.
stub
(
WaitModule
,
'default'
);
this
.
resetWait
();
this
.
store
=
Redux
.
createStore
(
Redux
.
combineReducers
(
reducers
),
Redux
.
compose
(
Redux
.
applyMiddleware
(
ReduxThunk
.
default
)
)
);
this
.
actions
=
Redux
.
bindActionCreators
(
actions
,
this
.
store
.
dispatch
);
this
.
registerChangeListener
=
(
fn
)
=>
{
return
registerChangeListener
(
this
.
store
,
fn
);
};
this
.
title
=
stubs
.
createStubTitle
(
1
,
'Foo'
);
this
.
el
=
$
(
'<a>'
).
attr
(
'href'
,
'/wiki/Foo'
).
get
(
0
);
this
.
actions
.
boot
(
/* initiallyEnabled: */
{
page
:
constant
(
true
)
},
/* user */
stubs
.
createStubUser
(
true
),
/* userSettings: */
{
getPreviewCount
:
constant
(
1
)
},
/* config: */
{
get
:
identity
}
);
this
.
dwell
=
(
title
,
el
,
ev
,
fetchResponse
,
resolution
=
FETCH_RESOLUTION
.
RESOLVE
)
=>
{
this
.
resetWait
();
return
this
.
actions
.
linkDwell
(
title
,
el
,
ev
,
{
fetchPreviewForTitle
()
{
const
method
=
resolution
===
FETCH_RESOLUTION
.
RESOLVE
?
'resolve'
:
'reject'
;
const
abort
=
{
abort
()
{}
};
return
$
.
Deferred
()[
method
](
fetchResponse
).
promise
(
abort
);
}
},
()
=>
'pagetoken'
,
previewTypes
.
TYPE_PAGE
);
};
this
.
dwellAndShowPreview
=
(
title
,
el
,
ev
,
fetchResponse
,
reject
=
FETCH_RESOLUTION
.
RESOLVE
)
=>
{
const
dwelled
=
this
.
dwell
(
title
,
el
,
ev
,
fetchResponse
,
reject
);
// Resolve the wait timeout for the linkDwell and the fetch action
this
.
waitDeferred
.
resolve
();
return
dwelled
;
};
this
.
abandon
=
()
=>
{
this
.
resetWait
();
return
this
.
actions
.
abandon
();
};
this
.
abandonAndWait
=
()
=>
{
const
abandoned
=
this
.
abandon
();
this
.
waitDeferred
.
resolve
();
return
abandoned
;
};
this
.
dwellAndPreviewDwell
=
(
title
,
el
,
ev
,
res
)
=>
{
return
this
.
dwellAndShowPreview
(
title
,
el
,
ev
,
res
).
then
(
()
=>
{
// Get out of the link, and before the delay ends...
const
abandonPromise
=
this
.
abandon
(),
abandonWaitDeferred
=
this
.
waitDeferred
;
// Dwell over the preview
this
.
actions
.
previewDwell
(
el
);
// Then the abandon delay finishes
abandonWaitDeferred
.
resolve
();
return
abandonPromise
;
}
);
};
}
}
);
QUnit
.
test
(
'it boots in INACTIVE state'
,
function
(
assert
)
{
const
state
=
this
.
store
.
getState
();
assert
.
strictEqual
(
state
.
preview
.
activeLink
,
undefined
,
'The initial active link is undefined.'
);
assert
.
strictEqual
(
state
.
preview
.
linkInteractionToken
,
undefined
,
'The initial token is undefined.'
);
}
);
QUnit
.
test
(
'in INACTIVE state, a link dwell switches it to ACTIVE'
,
function
(
assert
)
{
const
gateway
=
{
fetchPreviewForTitle
()
{
$
.
Deferred
().
promise
();
}
};
this
.
actions
.
linkDwell
(
this
.
title
,
this
.
el
,
'event'
,
gateway
,
constant
(
'pagetoken'
)
);
const
state
=
this
.
store
.
getState
();
assert
.
strictEqual
(
state
.
preview
.
activeLink
,
this
.
el
,
'It has an active link'
);
assert
.
strictEqual
(
state
.
preview
.
shouldShow
,
false
,
'Initializes with NO_DATA'
);
}
);
QUnit
.
test
(
'in ACTIVE state, fetch end switches it to DATA'
,
function
(
assert
)
{
const
store
=
this
.
store
,
el
=
this
.
el
;
return
this
.
dwellAndShowPreview
(
this
.
title
,
el
,
'event'
,
42
)
.
then
(
()
=>
{
const
state
=
store
.
getState
();
assert
.
strictEqual
(
state
.
preview
.
activeLink
,
el
,
'The active link is passed.'
);
assert
.
strictEqual
(
state
.
preview
.
shouldShow
,
true
,
'Should show when data has been fetched'
);
}
);
}
);
QUnit
.
test
(
'in ACTIVE state, fetch fail switches it to DATA'
,
function
(
assert
)
{
const
store
=
this
.
store
,
el
=
this
.
el
;
return
this
.
dwellAndShowPreview
(
this
.
title
,
el
,
'event'
,
42
,
FETCH_RESOLUTION
.
REJECT
).
then
(
()
=>
{
const
state
=
store
.
getState
();
assert
.
strictEqual
(
state
.
preview
.
activeLink
,
el
,
'The active link is passed.'
);
assert
.
strictEqual
(
state
.
preview
.
shouldShow
,
true
,
'Should show when data couldn\'t be fetched'
);
}
);
}
);
QUnit
.
test
(
'in ACTIVE state, abandon start, and then end, switch it to INACTIVE'
,
function
(
assert
)
{
const
el
=
this
.
el
;
return
this
.
dwellAndShowPreview
(
this
.
title
,
el
,
'event'
,
42
)
.
then
(
()
=>
{
return
this
.
abandonAndWait
(
el
);
}
).
then
(
()
=>
{
const
state
=
this
.
store
.
getState
();
assert
.
strictEqual
(
state
.
preview
.
activeLink
,
undefined
,
'After abandoning, preview is back to INACTIVE'
);
}
);
}
);
QUnit
.
test
(
'in ACTIVE state, abandon link, and then dwell preview, should keep it active after all delays'
,
function
(
assert
)
{
const
el
=
this
.
el
;
return
this
.
dwellAndPreviewDwell
(
this
.
title
,
el
,
'event'
,
42
)
.
then
(
()
=>
{
const
state
=
this
.
store
.
getState
();
assert
.
strictEqual
(
state
.
preview
.
activeLink
,
el
,
'The active link is passed.'
);
}
);
}
);
QUnit
.
test
(
'in ACTIVE state, abandon link, hover preview, back to link, should keep it active after all delays'
,
function
(
assert
)
{
const
el
=
this
.
el
;
// Dwell link, abandon it & hover preview
return
this
.
dwellAndPreviewDwell
(
this
.
title
,
el
,
'event'
,
42
)
.
then
(
()
=>
{
// Start abandoning the preview
const
abandonedPreview
=
this
.
abandon
();
const
abandonWaitDeferred
=
this
.
waitDeferred
;
// Dwell back into the link, new event ('event2') is triggered
const
dwelled
=
this
.
dwell
(
this
.
title
,
el
,
'event2'
,
42
);
const
dwellWaitDeferred
=
this
.
waitDeferred
;
// Preview abandon happens next, before the fetch
abandonWaitDeferred
.
resolve
();
// Then dwell wait & fetch happens
dwellWaitDeferred
.
resolve
();
return
$
.
when
(
abandonedPreview
,
dwelled
);
}
)
.
then
(
()
=>
{
const
state
=
this
.
store
.
getState
();
assert
.
strictEqual
(
state
.
preview
.
activeLink
,
el
,
'The active link is passed.'
);
}
);
}
);
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Sat, May 16, 12:34 (1 d, 4 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
77/80/390ab44d1bb7379470bdf6a8ad8b
Default Alt Text
integration.test.js (7 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment