UNPKG

apostrophe

Version:
288 lines (261 loc) • 9.36 kB
const t = require('../test-lib/test.js'); const assert = require('assert'); describe('content-i18n', function() { let apos; const config = { root: module, // Wrong port, but that is OK for this test baseUrl: 'http://localhost:3000', modules: { '@apostrophecms/i18n': { options: { locales: { en: { label: 'English' }, 'en-CA': { label: 'Canadian English', prefix: '/ca-en' }, 'fr-CA': { label: 'Canadian French', prefix: '/ca-fr' }, 'es-MX': { label: 'Mexico', hostname: 'example.mx', // Yup, it's not RTL, but this is just a test direction: 'rtl' } } } }, '@apostrophecms/express': { options: { // Allows us to inject an X-Forwarded-Host header for test purposes trustProxy: true } }, 'default-page': {}, '@apostrophecms/page': { options: { park: [ { parkedId: 'people', type: 'default-page', slug: '/people', title: 'People' } ] } } } }; this.timeout(t.timeout); after(function() { return t.destroy(apos); }); // EXISTENCE it('should replicate key docs across locales at startup', async function() { apos = await t.create(config); const homes = await apos.doc.db.find({ parkedId: 'home' }).toArray(); // Draft and published assert(homes.length === 8); const archives = await apos.doc.db.find({ parkedId: 'archive' }).toArray(); assert(archives.length === 8); // Make sure all archive docs have the archived property set `true` assert(!archives.find(archive => !archive.archived)); const globals = await apos.doc.db.find({ type: '@apostrophecms/global' }).toArray(); assert(globals.length === 8); const people = await apos.doc.db.find({ parkedId: 'people' }).toArray(); assert(people.length === 8); // People page in fr-CA has expected parked properties const req = apos.task.getReq(); const peoplePageEn = await apos.page.find(req, { parkedId: 'people' }).toObject(); const frCAReq = apos.task.getReq({ locale: 'fr-CA' }); let peoplePageFrCA = await apos.page.find(frCAReq, { parkedId: 'people' }).toObject(); assert(peoplePageEn.aposDocId === peoplePageFrCA.aposDocId); assert(peoplePageEn.aposLocale === 'en:published'); assert(peoplePageFrCA.aposLocale === 'fr-CA:published'); assert(peoplePageEn.title === 'People'); assert(peoplePageFrCA.title === 'People'); peoplePageFrCA.title = 'Altered'; await apos.page.update(frCAReq, peoplePageFrCA); peoplePageFrCA = await apos.page.find(frCAReq, { parkedId: 'people' }).toObject(); assert(peoplePageFrCA.title === 'People'); }); let home; it('should not replicate redundantly on a second startup in same db, but should repark parked properties', async function() { const apos2 = await t.create({ ...config, shortName: apos.options.shortName }); const homes = await apos2.doc.db.find({ parkedId: 'home' }).toArray(); // Draft and published assert(homes.length === 8); home = homes.find(home => home.aposLocale === 'en:published'); const people = await apos2.doc.db.find({ parkedId: 'people' }).toArray(); assert(people.length === 8); const archives = await apos2.doc.db.find({ parkedId: 'archive' }).toArray(); assert(archives.length === 8); const globals = await apos2.doc.db.find({ type: '@apostrophecms/global' }).toArray(); assert(globals.length === 8); const frCAReq = apos2.task.getReq({ locale: 'fr-CA' }); const peoplePageFrCA = await apos2.page.find(frCAReq, { parkedId: 'people' }).toObject(); // Restored to parked value assert(peoplePageFrCA.title === 'People'); await apos2.destroy(); }); let child, jar; it('should have just one locale for a newly inserted draft page', async function() { const req = apos.task.getReq({ mode: 'draft' }); child = await apos.page.insert(req, '_home', 'lastChild', { title: 'Child Page', type: 'default-page' } ); const versions = await apos.doc.db.find({ aposDocId: child.aposDocId }).toArray(); assert(versions.length === 1); }); it('should be able to insert test user', async function() { const user = apos.user.newInstance(); user.title = 'admin'; user.username = 'admin'; user.password = 'admin'; user.email = 'ad@min.com'; user.role = 'admin'; return apos.user.insert(apos.task.getReq(), user); }); it('REST: should be able to log in as admin', async function() { jar = apos.http.jar(); await apos.http.post('/api/v1/@apostrophecms/login/login', { body: { username: 'admin', password: 'admin', session: true }, jar }); const page = await apos.http.get('/', { jar }); assert(page.match(/logged in/)); assert(page.includes(`<a href="/api/v1/@apostrophecms/page/${home._id}/locale/en-CA">Canadian English (en-CA)</a>`)); }); it('localize API should succeed', async function() { return apos.http.post(`/api/v1/@apostrophecms/page/${child._id}/localize`, { body: { toLocale: 'en-CA' }, jar }); }); it('after localizing child page should exist in 2 locales', async function() { const versions = await apos.doc.db.find({ aposDocId: child.aposDocId }).toArray(); assert(versions.length === 2); assert(!versions.find(version => version.title !== 'Child Page')); const reqEn = apos.task.getReq({ locale: 'en', mode: 'draft' }); const en = await apos.doc.find(reqEn, { slug: '/child-page' }).toObject(); assert(en); assert.strictEqual(en._url, 'http://localhost:3000/child-page'); await apos.page.publish(reqEn, en); const reqEnCA = apos.task.getReq({ locale: 'en-CA', mode: 'draft' }); const enCA = await apos.doc.find(reqEnCA, { slug: '/child-page' }).toObject(); assert(enCA); assert.strictEqual(enCA._url, 'http://localhost:3000/ca-en/child-page'); // Distinguish the content in this locale enCA.title = 'Child Page, Toronto Style'; assert(apos.page.update(reqEnCA, enCA)); // Not published yet try { await apos.http.get('/ca-en/child-page', {}); assert(false); } catch (e) { assert(e.status === 404); } await apos.page.publish(reqEnCA, enCA); // Now it should work const childPage = await apos.http.get('/ca-en/child-page', {}); assert(childPage.includes('<title>Child Page, Toronto Style</title>')); // Navigation links are localized assert(childPage.includes('"http://localhost:3000/ca-en/">Home: /')); assert(childPage.includes('"http://localhost:3000/ca-en/child-page">Tab: /child-page')); // Locale-switching links are present for locales that are available // and fall back to home page for locales that are not const childPageId = enCA._id.replace(':draft', ':published'); assert(childPage.includes(`"/api/v1/@apostrophecms/page/${childPageId}/locale/en">English (en)(ltr)</a></li>`)); assert(childPage.includes(`"/api/v1/@apostrophecms/page/${childPageId}/locale/en-CA">Canadian English (en-CA)(ltr)</a></li>`)); assert(childPage.includes('"http://localhost:3000/ca-fr/">Canadian French (fr-CA)(ltr)</a></li>')); assert(childPage.includes('"http://example.mx/">Mexico (es-MX)(rtl)</a></li>')); // And the home page should be reachable const home = await apos.http.get('/ca-en/'); assert(home); }); it('Mexico locale should be received when hostname is correct', async function() { const reqEsMX = apos.task.getReq({ locale: 'es-MX', mode: 'draft' }); let esMX = await apos.doc.find(reqEsMX, { slug: '/' }).toObject(); assert(esMX); assert.strictEqual(esMX._url, 'http://example.mx/'); // Distinguish the content in this locale esMX.title = 'Pagina De Inicio'; esMX = await apos.page.update(reqEsMX, esMX); await apos.page.publish(reqEsMX, esMX); // Without hostname, we default to English const homePage = await apos.http.get('/', {}); assert(homePage.includes('<title>Home</title>')); const homePageEsMX = await apos.http.get('/', { headers: { 'X-Forwarded-Host': 'example.mx' } }); assert(homePageEsMX.includes('<title>Pagina De Inicio</title>')); }); it('localize API should not succeed a second time without the update flag', async function() { try { await apos.http.post(`/api/v1/@apostrophecms/page/${child._id}/localize`, { body: { toLocale: 'en-CA' }, jar }); assert(false); } catch (e) { assert(e.status === 409); } }); it('localize API should succeed a second time with the update flag', async function() { return apos.http.post(`/api/v1/@apostrophecms/page/${child._id}/localize`, { body: { toLocale: 'en-CA', update: true }, jar }); }); });