.catch is only available with jQuery 3, which is only now starting to
roll out (see https://phabricator.wikimedia.org/T124742)
This patch rolls back the usage of .catch introduced in
https://gerrit.wikimedia.org/r/#/c/373327/ to use .fail, but only the
source part, given that patch introduced unit tests for this behavior
Bug: T174724
Change-Id: I6e1c342d812b35846061266bc59e493e87423fd8
We cannot serve .map files from production servers. This makes
Popups extension difficult to debug. As a simplest solution we
decided to store map files as .json files so we can easily access
js maps files.
Changes:
- changed webpack config to store map files under .json extension
Bug: T173491
Change-Id: Iaa55f75a8c5f3e8f1f169b3ac33241cc54f0413f
Number.isNaN is a new function introduced in ECMAScript 6.
MediaWiki only requires ECMAScript 5 supports from browsers.
Notably, Opera 12 does not have Number.isNaN. Instead, use
the global isNaN function (which behaves the same except for
non-numeric inputs).
Change-Id: If436cd26b21ce0336dfbc37144f6226e7b948e5e
Instead of using the non-standard old Promise implementation by relying
on .fail, migrate it to .catch.
In this specific case, where we were chaining promises with $.when, the
semantics from going from fail to catch actually change. .fail keeps the
promise in a rejected state, while .catch will change it to resolved
unless another error is thrown.
As such, when changing it to .catch, the catched error will be re-thrown
to keep the promise in a rejected state, so that $.when.then is not
executed.
Additional changes:
* Make actions.js#fetch return its promise for ease of testing.
* Test FETCH_FAILED, which was fully untested.
Bug: T173819
Change-Id: Ibd380b714586979c6e60b4c969d17f36a0796b52
Introduce PopupsAnonsExperimentalGroupSize config variable. This defines
a population size who will be subject to experimentation. If the group
size is undefined or 0 (default) and PopupsBetaFeature is false
(default value) Popups will be enabled for everyone. If it is any other
value, half that group will see page previews.
Drop the config variable PopupsSchemaSamplingRate - we will now only
EventLog when an experiment is occuring. This means we can simplify the
MWEventLogger class as shouldLog will always be truthy. Given server
side eventlogging is only used for preference changes
traffic should be low and not need sampling.
Introduce getUserBucket which determines whether a user is in a bucket
on, off or control based on the value of
PopupsAnonsExperimentalGroupSize. Add tests showing how these
buckets are calculated.
Caution:
A kill switch wgPopupsEventLogging is provided for safety.
It defaults to false. Before merging, please check if any config changes
are necessary.
Bug: T171853
Change-Id: If2a0c5fceae78262c44cb522af38a925cc5919d3
There are some cases when the preview count stored in local storage
evaluates to NaN. When this happens we should override the value
to zero, store it in localStorage, and return it.
Bug: T168371
Change-Id: Ic44b7c7b5b716f6a0859f33278d56d2d95bbfb3e
We haven't seen the PP EventLogging instrumentation produce duplicate events
for weeks.
Bug: T172106
Change-Id: I6f3d7c0cdbf23161f63259e4d20d8a710376468b
Under some unknown circumstances getPreviewCountBucket() is called
with a value that is not a -1 or a natural number. When that happens
function returns 'undefined bucket' which causes eventLogging to
fail. I wasn't able to reproduce the issue, it might be specific
to browser/os. The safest way is to return 'unknown' for any other
case.
Bug: T168371
Change-Id: I374bb629762a86ac06a18e775d3c1a14682c9f55
Instead of registering global variables in a function, make it pure
return the external interface and set it to mw.popups in the
src/index.js entry point.
Explicitly comment on index.js what is being set and why.
Bug: T171287
Change-Id: I94d467bfa7fa6e56033dd254518ad50b5dde5bfc
Changes:
- introduced js module defining mw.popups object
- introduced isEnabled() method which checks the redux store to retrieve
isEnabled status
Bug: T171287
Change-Id: I523369831e2aa8a915ed1cb001b35d13b770f9da
Why: Because they are the approved standard by TC39 and Ecma for
JavaScript modules.
Changes:
* Wrap mw-node-qunit in run.js to register babel to transpile modules
for node v6
* Change all sources in src/ to use ES modules
* Change constants.js to be able to run without
jQuery.bracketedDevicePixelRatio given ES modules are hoisted to
the top by spec so we can't patch globals before importing it
* Change all tests in tests/node-qunit/ to use ES modules
* Drop usage of mock-require given ES modules are easy to stub with
sinon
Additional changes:
* Rename tests/node-qunit/renderer.js to renderer.test.js to follow
the convention of all the other files
* Make npm run test:node run only .test.js test files so that it
doesn't run the stubs.js or run.js file.
Bug: T171951
Change-Id: I17a0b76041d5e2fd18e2d54950d9d7c0db99a941
Previously, if the browser didn't support the Beacon API, then
instrumentation/eventLogging#isEnabled would bucket the user with a
sampling rate of 0, which is equivalent to returning false. This change
simply does the latter.
Additional changes:
* Update the documented module names of the instrumentation/eventLogging
and statsv modules.
Bug: T168847
Change-Id: I7ae5c10da42ca614b5b1a6619f9555e5665344cf
We had instrumentation for over 4 weeks and duplicate events rate
was very low. We want to keep stats so we check the duplicate events
rate but there is no need to filter those.
Bug: T167365
Change-Id: I72585beb21e9db589e45eeace657ef25f432abc9
Changes:
- introduced new event 'disabled', sent from settings popup
- added unit tests for 'disabled' event handling
Bug: T167365
Change-Id: I048b38122b8843199c86fd1ed9ec2ff21767e114
In order to debug the EventLogging instrumentation in production
environments, we want to be able to bucket ourselves at will.
When the debug flag (?debug=true) is passed send all events
for given page view.
Bug: T168847
Change-Id: Id1b13b0ecaa791b4f26be4d1151bdbbe5270b64d
Changes:
- when event doesn't have linkInteractionToken do not check for
duplicated tokens
- hygiene, move event duplication logic into separate functions
for better readability
Bug: T168449
Change-Id: I3ae197567ec9f67e104af109d4f1a1c1a6769d32
Following on from I4f653bba, since the schema and statsvInstrumentation
modules are similar, let's group/rename them:
schema -> instrumentation/eventLogging
statsvInstrumentation -> instrumentation/statsv
Change-Id: Ic59e0da7d4917f6733fd090f15d3c269af863f05
Currently, the mw.eventLog.Schema class samples per pageview. However,
we expect that if a user is bucketed for a session, then all
EventLogging events logged during that session are in the sample.
Moreover, loading the class in the way that we did - asynchronously,
using mw.loader#using - introduced an issue where the eventLogging
change listener would subscribe in the next tick of the JavaScript VM's
event loop and miss the "pageLoaded" event being queued (see T167273).
Changes:
* Make the schema module follow the form of the statsvInstrumentation
module, i.e. make it expose the #isEnabled method, and add the
associated getEventLoggingTracker function.
* Update the eventLogging change listener accept the tracker returned by
getEventLoggingTracker.
* Update/fix related JSDoc documentation.
Bug: T167236
Bug: T167273
Change-Id: I4f653bbaf1bbc2c2f70327e338080e17cd3443d4
preview/model is just a module/namespace object, not a builder class or
similar.
This patch changes a couple of imports to reference some of the exposed
functions of the preview/model where required.
In a shiny future, this pattern would be:
const { createModel, createNullModel } =
require( '../preview/model' )
Bug: T165018
Change-Id: If6ad4611538ca4f24e2443c0c3ed433275e995a6
gateway/*/rest were copies of gateway/restProvider just passing
a different provider. Docs were the same, they were untested, and
looking at them they seemed like unnecessary abstraction.
This patch removes the plain vs html structure, and separates gateways
like before, by endpoint.
There is a light utility in gateway/restFormatters.js that adapts the
call from the rest gateway to use formatters.js functions. It needs
testing, that I'll add in the next patch.
The flow for creating a gateway ends up as follows:
1. index.js calls gateway/index#createGateway( mw.config )
2. createGateway chooses based on wgPopupsGateway and invokes
* mediawiki.js#createMediaWikiApiGateway or
* rest.js#createRESTBaseGateway w/ restFormatters.js#parsePlainTextResponse or
* rest.js#createRESTBaseGateway w/ restFormatters.js#parseHTMLResponse
Changes:
* Removed src/gateway/{plain,html}/rest.js
* Extracted formatter functions to src/gateway/restFormatters.js
* src/gateway/plain/mediawiki.js -> src/gateway/mediawiki.js
* tests/node-qunit/gateway/plain/mediawiki.test.js ->
tests/node-qunit/gateway/mediawiki.test.js
* gateway/restProvider{,.test}.js -> gateway/rest{,.test}.js
* Change gateway/index.js#createGateway to properly call the rest
gateways with the rest formatters
Bug: T165018
Change-Id: Ia75695dfc192aad5bc581a68882514bad6c29646
And add tests, given it is growing in complexity.
Additional changes:
* Interface ext.popups.Gateway -> Gateway in docs
Bug: T165018
Change-Id: I8a12333ad9d14d6a7fbde11afc42f607881e8ea3
... from the statsvInstrumentation module so that the bucketing logic
can be shared with other instrumentation modules.
Change-Id: I5732fa539a3911939fa85fa88c102fa8dcfa5613
Refactor existing Restbase gateway and extract shared logic into
shared Restbase provider. Also introduced new createNullModel()
which defines an empty preview model.
Additionally improve naming in new gateways/formatter so function
names are more explicity.
* Htmlize() became formatPlainTextExtract() as it should be used
only with plain text extracts
* removeEllipsis() became removeTrailingEllipsis() as it removes
only trailing ellipsis.
* src/gateway/index.js defines gateways by configuration name stored
in extension.json
Bug: T165018
Change-Id: Ibe54dddfc1080e94814d1562d41e85cb6b43bfc1
Depends-On: I4f42c61b155a37c5dd42bc40034583865abd5d7a
Follows-up 79f3b318d0.
Number#toString supports up to Base 32.
Same collision behaviour but with a shorter string.
Typical length with Base 32: 7 (max: 11)
Typical length with Base 16: 9 (max: 14)
Change-Id: I91e91341cbecdec24549ace6a6300550f5b449ee
This reduces the number of 301 Redirect responses when fetching previews
from RESTBase.
Bug: T167633
Change-Id: I830947ab79e72dcc023193412c8d5bcee986e23f
Page Previews should be able to consume HTML response generated by
MediaWiki. First we need to move out plain text crunching from
renderer.js and model.js. Mediawiki and Restbase gateways will have
to parse/htmlize plaintext into nice HTML by themselves.
Bug: T165018
Change-Id: I5d7e9f610bb809aa9fb035a4a9f96e9e8796c9d8
...instead of 1 event per link
Supporting changes:
* Delegate events on the container when booting up
* Check eligibility of title on event triggered
* Pass the title from the event handlers into the actions instead of
storing it in the dom
* Add title.fromElement as sugar over isvalid(gettitle())
* Not tested as it is sugar over the other 2 functions
* Fix action tests and integration tests
processLinks to be removed next
Bug: T165572
Change-Id: I4d9837706dc77ec64121ac94410c0d2da83692e4
... and update the RESTBASE_PROFILE constant to the latest "stable"
profile for the endpoint.
Prior to this change the Accept header sent by the rest gateway was
application/json; charset=utf-8profile="..."
This was discovered while responding to T166605.
Change-Id: I00f277e724c561634b26c9ab10bd35332c6dba91
When there's an interaction, then the "tapped settings cog" event should
have the same properties set as the other interaction-specific events.
This was discovered while QAing T164256.
Bug: T164256
Change-Id: I4749b52656203c7e0c42ae742556ee996eee322a
... and the previewType property as well.
Per the Popups schema [0], the "opened" action should have the
perceivedWait and previewType properties set.
Bug: T166323
Change-Id: I957d123434a6b750aff6f5279865321a08367382
Changes:
* Assign exports to exports rather than reassigning module.exports so
that JSDoc can guess inner members.
* Tidy up parameter types with JSDoc's "nullable" syntax.
Bug: T158236
Change-Id: I7261d1bb3924c9f14301490f54d7813dcffc959b
Given that interactions end up with an event logged, there shouldn't be
a reason to keep an interaction active after it's corresponding final
event has been logged. See Tbayer's state graph.
This patch removes the current interaction if an event with that token
is logged, effectively finalizing it and making it impossible for the
token to be reused from the state tree again.
Additional changes:
* Pass the logged event with the action EVENT_LOGGED so that the reducer
can determine if it needs to do anything else.
* Since the interaction is removed, when undefined, guard against
actions that use state.interaction freely. (Only allow BOOT,
LINK_PREVIEW, and EVENT_LOGGED)
Bug: T161769
Bug: T163198
Change-Id: I99fd5716dc17da32929b6e8ae4aa164f9d84c387
This fixes a bug in I8a63d82, where the pageTitleHover and
namespaceIdHover properties of EventLogging events weren't being set.
Bug: T164256
Change-Id: Ie2c2d253f6508b89d48129fd17a902e5ded7cad5
Action changes:
* Include the namespace ID in LINK_DWELL.
Reducer changes:
* Add the createEvent helper, which adds the pageTitleHover and
namespaceIdHover properties in the event.
* Create "dismissed", "dwelledButAbandoned", and "opened" events using
the createEvent helper.
Additional changes:
* Store the target page's associated mw.Title using jQuery.
* Update the eventLogging reducer's test cases so that all LINK_DWELL
representations include title and namespaceID attributes.
* Create the createStubTitle factory function, which returns a minimal
usable mw.Title stub, and use it in the actions and integration test
cases.
Bug: T164256
Change-Id: I8a63d82a65324680dff9176020a8ea97695428c4
It enables certain optimizations, see:
* https://webpack.js.org/guides/production-build/
Code is minified by uglifyjs.
Aditional changes:
* Add banner so that sources are not minified by ResourceLoader
Bug: T160061
Change-Id: I50c9148ebf2d860db42a24225bc128bfcfe56927
I6a38a261 made the eventLogging change listener count and discard
duplicate events and count duplicate tokens.
While we isolate the issue(s) that lead to duplication (reuse, likely)
of tokens, make the eventLogging change listener discard events with
duplicate tokens as well.
Bug: T161769
Bug: T163198
Change-Id: I0dbb16c37814d39d7aec35c8fb7cc7309704c550
Binding the behavior has been left out as it requires some refactoring.
Ideally, that functionality should be tested via integration tests, which
is already done.
Bug: T133022
Change-Id: If2fd472847eb3557de97c7ec9619e8831e9bda6d