diff --git a/src/backend/mocks/default_handlers.js b/src/backend/mocks/default_handlers.js
index 64a18d4e..62367054 100644
--- a/src/backend/mocks/default_handlers.js
+++ b/src/backend/mocks/default_handlers.js
@@ -1,9 +1,290 @@
-// import { http, HttpResponse } from 'msw'
+import { http } from 'msw'
-// implementations for msw v2 handlers go in this file
-// see old.default_handlers.js for reference
-// this note can get removed after migration
+const myWikis = JSON.parse(localStorage.getItem('msw-myWikis')) || []
+let lastWikiId = (myWikis.length && myWikis[myWikis.length - 1].id) || 0
+let user = makeUser()
+let getEntityImportCalledTimes = 0
+
+function makeUser (email = 'test@local') {
+ return {
+ id: 1,
+ email,
+ verified: true,
+ created_at: '2020-01-01',
+ updated_at: '2020-01-01',
+ }
+}
+
+const makeNewWiki = ({ domain, sitename }) => {
+ const newWiki = {
+ id: ++lastWikiId,
+ domain,
+ sitename,
+ deleted_at: null,
+ created_at: '2020-01-01',
+ updated_at: '2020-01-01',
+ pivot: {
+ user_id: user.id,
+ wiki_id: lastWikiId,
+ },
+ wiki_managers: [{
+ email: user.email,
+ pivot: {
+ user_id: user.id,
+ wiki_id: lastWikiId,
+ },
+ }],
+ wiki_db_version: {
+ id: 101,
+ wiki_id: lastWikiId,
+ version: 'mw1.33-wbs1',
+ },
+ public_settings: [],
+ }
+
+ myWikis.push(newWiki)
+ localStorage.setItem('msw-myWikis', JSON.stringify(myWikis))
+
+ return newWiki
+}
+
+const removeWiki = wikiIndex => {
+ myWikis.splice(wikiIndex, 1)
+ localStorage.setItem('msw-myWikis', JSON.stringify(myWikis))
+}
+
+const wikiDiscovery = (referrer, params) => {
+ const pseudorandom = {
+ seed: 1,
+ next: function () {
+ const x = Math.sin(this.seed++) * 10000
+ return x - Math.floor(x)
+ },
+ }
+
+ const names = [
+ 'Wikibase Name',
+ 'A Very Long Wikibase Name',
+ ]
+
+ let wikis = [...Array(75).keys()].map((id) => {
+ const wiki = {
+ id,
+ domain: id + '-wikibase.wbaas.localhost',
+ sitename: id + ' - ' + names[id % names.length],
+ wiki_site_stats: null,
+ logo_url: null,
+ }
+
+ if (pseudorandom.next() >= 0.1) {
+ wiki.wiki_site_stats = {
+ pages: Math.ceil(pseudorandom.next() * 250),
+ }
+ }
+
+ if (pseudorandom.next() >= 0.5) {
+ wiki.logo_url = new URL(referrer).origin + '/favicon.ico'
+ }
+ return wiki
+ })
+
+ if (parseInt(params.get('is_active'))) {
+ wikis = wikis.filter((wiki) => {
+ const stats = wiki.wiki_site_stats
+ return stats && stats.pages > 1
+ })
+ }
+
+ if (params.get('sort') === 'sitename') {
+ wikis = wikis.sort((a, b) => {
+ let sort = a.sitename.localeCompare(b.sitename, 'en', { numeric: true })
+ if (params.get('direction') === 'desc') {
+ sort *= -1
+ }
+ return sort
+ })
+ }
+
+ if (params.get('sort') === 'pages') {
+ wikis = wikis.sort((a, b) => {
+ const aPages = a.wiki_site_stats ? a.wiki_site_stats.pages : 0
+ const bPages = b.wiki_site_stats ? b.wiki_site_stats.pages : 0
+ if (params.get('direction') === 'desc') {
+ return bPages - aPages
+ }
+ return aPages - bPages
+ })
+ }
+
+ const currentPage = parseInt(params.get('page'))
+ const resultsPerPage = parseInt(params.get('per_page'))
+ const start = (currentPage - 1) * resultsPerPage
+ const end = start + resultsPerPage
+
+ return {
+ data: wikis.slice(start, end),
+ meta: {
+ last_page: Math.ceil(wikis.length / resultsPerPage),
+ total: wikis.length,
+ },
+ }
+}
export const handlers = [
+ http.get('/api/auth/login', ({ cookies }) => {
+ const { authToken } = cookies
+ if (authToken !== 'token_value') {
+ return Response.json('Unauthorized', {
+ status: 401,
+ })
+ }
+
+ user = makeUser()
+ return Response.json({ user })
+ }),
+
+ http.post('/api/auth/login', async ({ request }) => {
+ const body = await request.json()
+ user = makeUser(body.email)
+
+ return Response.json({ user }, {
+ headers: { 'set-cookie': 'authToken=token_value' },
+ })
+ }),
+
+ http.delete('/api/auth/login', () => {
+ return new Response(null, { status: 204 })
+ }),
+
+ http.post('/api/user/forgotPassword', () => {
+ return new Response('Success')
+ }),
+
+ http.post('/api/user/resetPassword', () => {
+ return new Response('Success')
+ }),
+
+ http.post('/api/user/sendVerifyEmail', () => {
+ return new Response('Already verified')
+ }),
+
+ http.post('/api/user/verifyEmail', () => {
+ return new Response('Already verified')
+ }),
+
+ http.post('/api/complaint/sendMessage', () => {
+ return new Response('Success')
+ }),
+
+ http.post('/api/contact/sendMessage', async ({ request }) => {
+ const body = await request.json()
+
+ if (body.name === '' || body.message === '' || body.subject === '') {
+ return new Response(null, { status: 400 })
+ }
+
+ return new Response('Success')
+ }),
+
+ http.post('/api/wiki/mine', () => {
+ const data = { wikis: myWikis, count: myWikis.length, limit: false }
+ return Response.json(data)
+ }),
+
+ http.post('/api/wiki/entityImport', () => {
+ const data = { status: 'pending', payload: {}, started_at: new Date().toJSON() }
+ return Response.json(data)
+ }),
+
+ http.get('/api/wiki/entityImport', () => {
+ getEntityImportCalledTimes++
+ switch (getEntityImportCalledTimes) {
+ case 1:
+ return Response.json({ data: [] })
+ case 2:
+ return Response.json({ data: [{ status: 'pending' }] })
+ default:
+ return Response.json({ data: [{ status: 'success' }] })
+ }
+ }),
+
+ http.post('/api/wiki/create', async ({ request }) => {
+ const body = await request.json()
+ const newWiki = makeNewWiki(body)
+ return Response.json({
+ success: true,
+ data: newWiki,
+ })
+ }),
+
+ http.post('/api/wiki/delete', async ({ request }) => {
+ const body = await request.json()
+ const wikiId = body.wiki
+ const wikiIndex = myWikis.findIndex(w => w.id === Number(wikiId))
+
+ if (wikiIndex < 0) {
+ return new Response(null, { status: 404 })
+ }
+
+ removeWiki(wikiIndex)
+ return new Response('Success')
+ }),
+
+ http.post('/api/wiki/logo/update', () => {
+ return new Response('Success')
+ }),
+
+ http.post(/\/api\/wiki\/setting\/.*?\/update$/, () => {
+ return new Response('Success')
+ }),
+
+ http.post('/api/wiki/details', async ({ request }) => {
+ const body = await request.json()
+ const wikiId = body.wiki
+ const wikiDetails = myWikis.find(w => w.id === Number(wikiId))
+
+ if (!wikiDetails) {
+ return new Response(null, { status: 404 })
+ }
+
+ return Response.json({
+ success: true,
+ data: wikiDetails,
+ })
+ }),
+
+ http.get('/api/wiki', async ({ request }) => {
+ const referrer = await request.referrer
+ const url = new URL(await request.url)
+
+ return Response.json(wikiDiscovery(referrer, url.searchParams))
+ }),
+
+ http.get('/api/v1/policies/missing', () => {
+ const items = []
+ return Response.json({ items })
+ }),
+
+ http.get('/api/v1/policies/current', () => {
+ const items = [
+ {
+ metadata: {
+ policy_id: 2,
+ type: 'terms-of-use',
+ active_from: '2026-08-27',
+ content_vue_file: 'terms-of-use/version-2.vue',
+ },
+ },
+ {
+ metadata: {
+ policy_id: 3,
+ type: 'hosting-policy',
+ active_from: '2026-08-27',
+ content_vue_file: 'hosting-policy/version-1.vue',
+ },
+ },
+ ]
+ return Response.json({ items })
+ }),
]
diff --git a/src/backend/mocks/old.default_handlers.js b/src/backend/mocks/old.default_handlers.js
deleted file mode 100644
index 42278322..00000000
--- a/src/backend/mocks/old.default_handlers.js
+++ /dev/null
@@ -1,226 +0,0 @@
-// this file exists only as reference until all
-// legacy handlers are migrated to default_handlers.js
-
-import { rest } from 'msw'
-
-let myWikis = JSON.parse(localStorage.getItem('msw-myWikis')) || []
-let lastWikiId = (myWikis.length && myWikis[myWikis.length - 1].id) || 0
-let user = makeUser()
-let getEntityImportCalledTimes = 0
-
-function makeUser (email = 'test@local') {
- return {
- id: 1,
- email,
- verified: true,
- created_at: '2020-01-01',
- updated_at: '2020-01-01',
- }
-}
-
-const makeNewWiki = ({ domain, sitename }) => {
- const newWiki = {
- id: ++lastWikiId,
- domain,
- sitename,
- deleted_at: null,
- created_at: '2020-01-01',
- updated_at: '2020-01-01',
- pivot: {
- user_id: user.id,
- wiki_id: lastWikiId,
- },
- wiki_managers: [{
- email: user.email,
- pivot: {
- user_id: user.id,
- wiki_id: lastWikiId,
- },
- }],
- wiki_db_version: {
- id: 101,
- wiki_id: lastWikiId,
- version: 'mw1.33-wbs1',
- },
- public_settings: [],
- }
-
- myWikis.push(newWiki)
- localStorage.setItem('msw-myWikis', JSON.stringify(myWikis))
-
- return newWiki
-}
-
-const removeWiki = wikiIndex => {
- myWikis = myWikis.splice(wikiIndex, 1)
- localStorage.setItem('msw-myWikis', JSON.stringify(myWikis))
-}
-
-const wikiDiscovery = (referrer, params) => {
- const pseudorandom = {
- seed: 1,
- next: function () {
- const x = Math.sin(this.seed++) * 10000
- return x - Math.floor(x)
- },
- }
-
- const names = [
- 'Wikibase Name',
- 'A Very Long Wikibase Name',
- ]
-
- let wikis = [...Array(75).keys()].map((id) => {
- const wiki = {
- id,
- domain: id + '-wikibase.wbaas.localhost',
- sitename: id + ' - ' + names[id % names.length],
- wiki_site_stats: null,
- logo_url: null,
- }
-
- if (pseudorandom.next() >= 0.1) {
- wiki.wiki_site_stats = {
- pages: Math.ceil(pseudorandom.next() * 250),
- }
- }
-
- if (pseudorandom.next() >= 0.5) {
- wiki.logo_url = new URL(referrer).origin + '/favicon.ico'
- }
- return wiki
- })
-
- if (parseInt(params.get('is_active'))) {
- wikis = wikis.filter((wiki) => {
- const stats = wiki.wiki_site_stats
- return stats && stats.pages > 1
- })
- }
-
- if (params.get('sort') === 'sitename') {
- wikis = wikis.sort((a, b) => {
- let sort = a.sitename.localeCompare(b.sitename, 'en', { numeric: true })
- if (params.get('direction') === 'desc') {
- sort *= -1
- }
- return sort
- })
- }
-
- if (params.get('sort') === 'pages') {
- wikis = wikis.sort((a, b) => {
- const aPages = a.wiki_site_stats ? a.wiki_site_stats.pages : 0
- const bPages = b.wiki_site_stats ? b.wiki_site_stats.pages : 0
- if (params.get('direction') === 'desc') {
- return bPages - aPages
- }
- return aPages - bPages
- })
- }
-
- const currentPage = parseInt(params.get('page'))
- const resultsPerPage = parseInt(params.get('per_page'))
- const start = (currentPage - 1) * resultsPerPage
- const end = start + resultsPerPage
-
- return {
- data: wikis.slice(start, end),
- meta: {
- last_page: Math.ceil(wikis.length / resultsPerPage),
- total: wikis.length,
- },
- }
-}
-
-export const handlers = [
- /* User endpoints */
- rest.post(/\/api\/auth\/login$/, (req, res, ctx) => {
- user = makeUser(req.body.email)
- return res(ctx.json({
- user,
- }), ctx.cookie('authToken', 'token_value'))
- }),
- rest.get(/\/api\/auth\/login$/, (req, res, ctx) => {
- const { authToken } = req.cookies
- if (authToken !== 'token_value') {
- return res(ctx.status(401))
- }
- user = makeUser(req.body.email)
- return res(ctx.json({
- user,
- }))
- }),
- rest.delete(/\/api\/auth\/login$/, (req, res, ctx) => {
- user = makeUser(req.body.email)
- return res(ctx.status(204))
- }),
- rest.post(/\/api\/user\/forgotPassword$/, (req, res, ctx) => {
- if (req.body.email === 'serverError@example.com') {
- return res(ctx.status(400, 'Mocked Server Error'))
- }
- return res(ctx.status(200))
- },
- ),
- rest.post(/\/api\/user\/resetPassword$/, (_, res, ctx) => res(ctx.status(200))),
- rest.post(/\/api\/user\/sendVerifyEmail$/, (_, res, ctx) => res(ctx.json({ message: 'Already verified' }))),
- rest.post(/\/api\/user\/verifyEmail$/, (_, res, ctx) => res(ctx.status(200))),
- rest.post(/\/api\/complaint\/sendMessage$/, (req, res, ctx) => res(ctx.status(200))),
- rest.post(/\/api\/contact\/sendMessage$/, (req, res, ctx) => {
- if (req.body.name === 'recaptchaError') {
- return res(ctx.status(401, 'Mocked recaptcha Error'))
- }
- if (req.body.name === '') {
- return res(ctx.status(400, 'Mocked empty name Error'))
- }
- if (req.body.recaptcha === '') {
- return res(ctx.status(400, 'Mocked recaptcha empty Error'))
- }
- return res(ctx.status(200))
- },
- ),
-
- /* Wiki endpoints */
- rest.post(/\/api\/wiki\/entityImport$/, (_, res, ctx) => {
- return res(ctx.json({ data: { status: 'pending', payload: {}, started_at: new Date().toJSON() } }))
- }),
- rest.get(/\/api\/wiki\/entityImport$/, (_, res, ctx) => {
- getEntityImportCalledTimes++
- switch (getEntityImportCalledTimes) {
- case 1:
- return res(ctx.json({ data: [] }))
- case 2:
- return res(ctx.json({ data: [{ status: 'pending' }] }))
- default:
- return res(ctx.json({ data: [{ status: 'success' }] }))
- }
- }),
- rest.get(/\/api\/wiki\/count$/, (_, res, ctx) => res(ctx.json({ data: 1 }))),
- rest.post(/\/api\/wiki\/mine$/, (_, res, ctx) => res(ctx.json({ wikis: myWikis, count: myWikis.length, limit: false }))),
- rest.post(/\/api\/wiki\/create$/, (req, res, ctx) => {
- return res(ctx.json({ data: makeNewWiki(req.body) }))
- }),
- rest.post(/\/api\/wiki\/delete$/, (req, res, ctx) => {
- const wikiId = req.body.wiki
- const wikiIndex = myWikis.findIndex(w => w.id === Number(wikiId))
- if (wikiIndex < 0) {
- return res(ctx.status(404))
- }
-
- removeWiki(wikiIndex)
- return res(ctx.status(200))
- }),
- rest.post(/\/api\/wiki\/logo\/update$/, (_, res, ctx) => res(ctx.status(200))),
- rest.post(/\/api\/wiki\/setting\/.*?\/update$/, (_, res, ctx) => res(ctx.status(200))),
- rest.post(/\/api\/wiki\/details$/, (req, res, ctx) => {
- const wikiId = req.body.wiki
- const wikiDetails = myWikis.find(w => w.id === Number(wikiId))
- if (!wikiDetails) {
- return res(ctx.status(404))
- }
- return res(ctx.json({ data: wikiDetails }), ctx.status(200))
- }),
- rest.get(/\/api\/wiki$/, (req, res, ctx) => {
- return res(ctx.json(wikiDiscovery(req.referrer, req.url.searchParams)))
- }),
-]
diff --git a/src/main.js b/src/main.js
index e0279418..09f46070 100644
--- a/src/main.js
+++ b/src/main.js
@@ -12,53 +12,61 @@ import 'typeface-roboto/index.css'
import 'vuetify/dist/vuetify.min.css'
import config from '~/config'
-if (process.env.NODE_ENV !== 'production' && config.API_MOCK === '1') {
- const { worker } = require('./backend/mocks/browser')
- worker.start()
+async function enableMocking () {
+ if (process.env.NODE_ENV !== 'production' && config.API_MOCK === '1') {
+ const { worker } = await import('./backend/mocks/browser')
+
+ // `worker.start()` returns a Promise that resolves
+ // once the Service Worker is up and ready to intercept requests.
+ // onUnhandledRequest: 'error' saves us from a false belief that mocks are working when they aren't
+ return worker.start({ onUnhandledRequest: 'error' })
+ }
}
-Vue.config.productionTip = false
+enableMocking().then(() => {
+ Vue.config.productionTip = false
-Vue.use(Vuetify)
+ Vue.use(Vuetify)
-Vue.use(VueReCaptcha, {
- siteKey: config.RECAPTCHA_SITE_KEY,
- loaderOptions: { useRecaptchaNet: true },
-})
+ Vue.use(VueReCaptcha, {
+ siteKey: config.RECAPTCHA_SITE_KEY,
+ loaderOptions: { useRecaptchaNet: true },
+ })
-// allow components to access api without importing it
-Vue.prototype.$api = api
+ // allow components to access api without importing it
+ Vue.prototype.$api = api
-/* eslint-disable no-new */
-new Vue({
- el: '#app',
- router,
- store,
- vuetify: new Vuetify({
- icons: {
- iconfont: 'mdi',
- },
- }),
- components: { App },
- template: '',
- created: function () {
- store.dispatch('login', null)
- axios.interceptors.response.use(undefined, function (err) {
- return new Promise(function (resolve, reject) {
+ /* eslint-disable no-new */
+ new Vue({
+ el: '#app',
+ router,
+ store,
+ vuetify: new Vuetify({
+ icons: {
+ iconfont: 'mdi',
+ },
+ }),
+ components: { App },
+ template: '',
+ created: function () {
+ store.dispatch('login', null)
+ axios.interceptors.response.use(undefined, function (err) {
+ return new Promise(function (resolve, reject) {
// Unauthenticated. is the exact error message returned by the API for the auth middle ware
// which is why we check for that message here...
- if (err.response.config && !err.response.config.__isRetryRequest && err.response.data && err.response.data.error && err.response.data.error === 'Unauthenticated.') {
+ if (err.response.config && !err.response.config.__isRetryRequest && err.response.data && err.response.data.error && err.response.data.error === 'Unauthenticated.') {
// TODO this IF should also have a condition for is logged in....
- console.log('Detected logged out state, so logging out...')
- store
- .dispatch('logout')
- .then(() => router.push('/login'))
- .catch(err => {
- console.log(err)
- })
- }
- reject(err)
+ console.log('Detected logged out state, so logging out...')
+ store
+ .dispatch('logout')
+ .then(() => router.push('/login'))
+ .catch(err => {
+ console.log(err)
+ })
+ }
+ reject(err)
+ })
})
- })
- },
+ },
+ })
})