From 6bd26732239e19dde0d628547d574f6ce39e2404 Mon Sep 17 00:00:00 2001 From: jeremie Date: Fri, 17 Jan 2025 14:51:08 +0100 Subject: [PATCH] tech(back): remove useless script --- .../fix-obsolete-cloned-challenges/index.js | 78 ----- .../upload-multi-locales-to-phrase/index.js | 216 ------------ .../fix-obsolete-cloned-challenges_test.js | 155 --------- .../upload-multi-locales-to-phrase_test.js | 326 ------------------ 4 files changed, 775 deletions(-) delete mode 100644 api/scripts/fix-obsolete-cloned-challenges/index.js delete mode 100644 api/scripts/upload-multi-locales-to-phrase/index.js delete mode 100644 api/tests/scripts/fix-obsolete-cloned-challenges_test.js delete mode 100644 api/tests/scripts/upload-multi-locales-to-phrase_test.js diff --git a/api/scripts/fix-obsolete-cloned-challenges/index.js b/api/scripts/fix-obsolete-cloned-challenges/index.js deleted file mode 100644 index 9ac4649f7..000000000 --- a/api/scripts/fix-obsolete-cloned-challenges/index.js +++ /dev/null @@ -1,78 +0,0 @@ -import 'dotenv/config'; -import { performance } from 'node:perf_hooks'; -import { fileURLToPath } from 'node:url'; -import { disconnect, knex } from '../../db/knex-database-connection.js'; -import { logger } from '../../lib/infrastructure/logger.js'; -import { challengeRepository, releaseRepository } from '../../lib/infrastructure/repositories/index.js'; -import _ from 'lodash'; - -const __filename = fileURLToPath(import.meta.url); -const isLaunchedFromCommandLine = process.argv[1] === __filename; - -export async function revertObsoleteChallengesToOriginalStatus({ dryRun, scriptExectIdToFix, releaseId }) { - const challengeIds = await _getObsoleteChallengeIds({ scriptExectIdToFix }); - logger.info(`${challengeIds.length} épreuves récupérées et à traiter.`); - const release = await releaseRepository.getRelease(releaseId); - const challengeForReleaseByIds = _.keyBy(release.content.challenges, 'id'); - let updateCount = 0; - - for (const [index, challengeId] of challengeIds.entries()) { - const challengeForRelease = challengeForReleaseByIds[challengeId]; - if (!challengeForRelease) { - logger.warn(`(${index}/${challengeIds.length}) L'épreuve ${challengeId} n'a pas été trouvée dans la release.`); - continue; - } - if (_hasAttachment(challengeForRelease)) { - logger.warn(`(${index}/${challengeIds.length}) L'épreuve ${challengeId} a un attachment et ne doit donc pas être traité.`); - continue; - } - const currentChallenge = await challengeRepository.get(challengeId); - const previousStatus = currentChallenge.status; - currentChallenge.status = challengeForRelease.status; - currentChallenge.madeObsoleteAt = null; - logger.info(`(${index}/${challengeIds.length}) L'épreuve ${challengeId} va être passée du statut "${previousStatus}" au statut "${currentChallenge.status}"`); - ++updateCount; - if (!dryRun) { - await challengeRepository.update(currentChallenge); - } - } - - logger.info(`${updateCount} épreuves ont été rétablies.`); -} - -function _hasAttachment(challengeForRelease) { - return challengeForRelease.illustrationUrl || challengeForRelease.attachments?.length > 0; -} - -async function _getObsoleteChallengeIds({ scriptExectIdToFix }) { - return knex('focus_phrase') - .pluck('persistantId') - .where({ scriptExectId: scriptExectIdToFix, type: 'challenge' }); -} - -async function main() { - const startTime = performance.now(); - logger.info(`Script ${__filename} has started`); - const dryRun = process.env.DRY_RUN !== 'false'; - const scriptExectIdToFix = process.env.SCRIPT_ID; - const releaseId = process.env.RELEASE_ID; - - if (dryRun) logger.warn('Dry run: no actual modification will be performed, use DRY_RUN=false to disable'); - await revertObsoleteChallengesToOriginalStatus({ dryRun, scriptExectIdToFix, releaseId }); - const endTime = performance.now(); - const duration = Math.round(endTime - startTime); - logger.info(`Script has ended: took ${duration} milliseconds`); -} - -(async () => { - if (isLaunchedFromCommandLine) { - try { - await main(); - } catch (error) { - logger.error(error); - process.exitCode = 1; - } finally { - await disconnect(); - } - } -})(); diff --git a/api/scripts/upload-multi-locales-to-phrase/index.js b/api/scripts/upload-multi-locales-to-phrase/index.js deleted file mode 100644 index fd4803076..000000000 --- a/api/scripts/upload-multi-locales-to-phrase/index.js +++ /dev/null @@ -1,216 +0,0 @@ -import { Configuration, LocalesApi, UploadsApi } from 'phrase-js'; -import { Challenge } from '../../lib/domain/models/index.js'; -import _ from 'lodash'; -import { PassThrough, pipeline, Readable } from 'node:stream'; -import csv from 'fast-csv'; -import { logger } from '../../lib/infrastructure/logger.js'; -import { streamToPromise } from '../../lib/infrastructure/utils/stream-to-promise.js'; -import * as config from '../../lib/config.js'; -import { disconnect, knex } from '../../db/knex-database-connection.js'; -import { fileURLToPath } from 'node:url'; -import { - challengeRepository, - releaseRepository, - skillRepository, - translationRepository -} from '../../lib/infrastructure/repositories/index.js'; - -export async function uploadToPhrase({ scriptExectId }) { - const releaseId = await releaseRepository.create(); - const release = await releaseRepository.getRelease(releaseId); - - const clonedSkillsIdsChallengesIds = await knex('focus_phrase').select('*').where({ scriptExectId }); - - // type // persistante ID // - const clonedPersistantIds = clonedSkillsIdsChallengesIds.map(({ persistantId }) => persistantId); - - const challenges = (await challengeRepository.list()).filter(({ id }) => clonedPersistantIds.includes(id)); - const skills = (await skillRepository.list()).filter(({ id }) => clonedPersistantIds.includes(id)); - - const phraseApi = { Configuration, LocalesApi, UploadsApi }; - const releaseContent = Object.fromEntries( - Object.entries(release.content) - .map(([collection, entities]) => [ - collection, - Object.fromEntries(entities.map((entity) => [entity.id, entity])), - ]), - ); - const translations = await translationRepository.list(); - const translationSkills = translations.filter(({ key })=> { - return skills.find(({ id })=> { - const regex = new RegExp(`skill\\.${id}\\..+`, 'g'); - return !!key.match(regex); - }); - }); - const valideChallengesWithFRPrimaryOnly = challenges.filter((challenge) => challenge.primaryLocale === 'fr' && challenge.status === Challenge.STATUSES.VALIDE); - const translationChallenges = translations.filter(({ key })=> { - return valideChallengesWithFRPrimaryOnly.find(({ id })=> { - const regex = new RegExp(`challenge\\.${id}\\..+`, 'g'); - return !!key.match(regex); - }); - }); - const sortedLocales = _.uniq([...translationSkills.map(({ locale }) => locale), ...translationChallenges.map(({ locale }) => locale)]) - .sort((localeA, localeB) => localeA.localeCompare(localeB)); - const items = []; - items.push([ - 'key', - ...sortedLocales, - 'tags', - 'description', - ]); - items.push(..._generateItemsForSkills(translationSkills, releaseContent, sortedLocales)); - items.push(..._generateItemsForChallenges(translationChallenges, releaseContent, sortedLocales)); - - const stream = new PassThrough(); - - pipeline( - Readable.from(items), - csv.format({ headers: true }), - stream, - () => null, - ); - logger.info(`About to send ${items.length} to Phrase...`); - const csvFile = new File([await streamToPromise(stream)], 'translations.csv'); - const configuration = new phraseApi.Configuration({ - fetchApi: fetch, - apiKey: `token ${config.phrase.apiKey}`, - }); - - try { - const locales = await new phraseApi.LocalesApi(configuration).localesList({ - projectId: config.phrase.projectId, - }); - - const defaultLocaleId = locales.find((locale) => locale._default)?.id; - const keyIndex = 1; - const tagIndex = keyIndex + sortedLocales.length + 1; - const descriptionIndex = tagIndex + 1; - const localeMapping = Object.fromEntries(sortedLocales.map((locale, index) => [locale, index + keyIndex + 1])); - await new phraseApi.UploadsApi(configuration).uploadCreate({ - projectId: config.phrase.projectId, - localeId: defaultLocaleId, - file: csvFile, - fileFormat: 'csv', - updateDescriptions: false, - updateTranslations: false, - skipUploadTags: true, - localeMapping, - formatOptions: { - key_index: keyIndex, - tag_column: tagIndex, - comment_index: descriptionIndex, - header_content_row: true, - } - }); - } catch (e) { - const text = await e.text?.() ?? e; - logger.error(`Phrase error while uploading translations: ${text}`); - throw new Error('Phrase error', { cause: e }); - } -} - -const baseUrl = config.lcms.baseUrl; - -function _generateDescriptionForChallenge(challengeId, locales) { - const primaryLocalePreviewUrl = `Prévisualisation FR: ${baseUrl}/api/challenges/${challengeId}/preview`; - const alternativeLocalePreviewUrls = locales - .filter((locale) => locale !== 'fr') - .map((locale) => { - return `Prévisualisation ${locale.toUpperCase()}: ${baseUrl}/api/challenges/${challengeId}/preview?locale=${locale}`; - }); - const peURL = `Pix Editor: ${baseUrl}/challenge/${challengeId}`; - - return `${[primaryLocalePreviewUrl, ...alternativeLocalePreviewUrls, peURL].join('\n')}`; -} - -function _generateItemsForSkills(translationSkills, releaseContent, sortedLocales) { - const skillItems = []; - const translationsSkillByKey = _.groupBy(translationSkills, 'key'); - for (const [key, translations] of Object.entries(translationsSkillByKey)) { - const skillItem = []; - skillItem.push(key); - skillItem.push(...sortedLocales.map((locale) => { - const translationForLocale = translations.find((translation) => translation.locale === locale); - return translationForLocale?.value ?? ''; - })); - const skillTags = _generateTagsForSkill(key.split('.')[1], releaseContent); - skillItem.push(skillTags); - skillItem.push(''); - skillItems.push(skillItem); - } - return skillItems; -} - -function _generateItemsForChallenges(translationChallenges, releaseContent, sortedLocales) { - const challengeItems = []; - const translationsChallengeByKey = _.groupBy(translationChallenges, 'key'); - for (const [key, translations] of Object.entries(translationsChallengeByKey)) { - const challengeItem = []; - challengeItem.push(key); - challengeItem.push(...sortedLocales.map((locale) => { - const translationForLocale = translations.find((translation) => translation.locale === locale); - return translationForLocale?.value ?? ''; - })); - const challengeTags = _generateTagsForChallenge(key.split('.')[1], releaseContent); - const challengeDescription = _generateDescriptionForChallenge(key.split('.')[1], sortedLocales); - challengeItem.push(challengeTags); - challengeItem.push(challengeDescription); - challengeItems.push(challengeItem); - } - return challengeItems; -} - -function _generateTagsForSkill(skillId, release) { - const tags = _generateCommonTagPart(skillId, release); - const rawTags = `acquis,${tags}`; - return `${toTag(rawTags)}`; -} - -function _generateTagsForChallenge(challengeId, release) { - const challenge = release.challenges[challengeId]; - const tags = _generateCommonTagPart(challenge.skillId, release); - const challengeTag = `${tags.split(',')[0]}-${challenge.status}`; - const rawTags = `epreuve,${challengeTag},${tags}`; - return `${toTag(rawTags)}`; -} - -function _generateCommonTagPart(skillId, release) { - const skill = release.skills[skillId]; - const tube = release.tubes[skill.tubeId]; - const competence = release.competences[tube.competenceId]; - const area = release.areas[competence.areaId]; - const framework = release.frameworks[area.frameworkId]; - const frameworkTag = `${framework.name}`; - const areaTag = `${frameworkTag}-${area.code}`; - const competenceTag = `${areaTag}-${competence.index}`; - const tubeTag = `${competenceTag}-${tube.name}`; - const skillTag = `${tubeTag}-${skill.name}`; - return `${skillTag},${tubeTag},${competenceTag},${areaTag},${frameworkTag}`; -} - -function toTag(tagName) { - return _(tagName).deburr().replaceAll(' ', '_').replaceAll('@', ''); -} - -const __filename = fileURLToPath(import.meta.url); -const isLaunchedFromCommandLine = process.argv[1] === __filename; - -async function main() { - if (!isLaunchedFromCommandLine) return; - - try { - - const scriptExectId = process.env.SCRIPT_EXECT_ID; - if (!scriptExectId) throw new Error('le scriptExectId est obligatoire'); - - await uploadToPhrase({ scriptExectId }); - logger.info('All done'); - } catch (e) { - logger.error(e); - process.exitCode = 1; - } finally { - await disconnect(); - } -} - -main(); diff --git a/api/tests/scripts/fix-obsolete-cloned-challenges_test.js b/api/tests/scripts/fix-obsolete-cloned-challenges_test.js deleted file mode 100644 index 6dd63be3b..000000000 --- a/api/tests/scripts/fix-obsolete-cloned-challenges_test.js +++ /dev/null @@ -1,155 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest'; -import { domainBuilder, knex } from '../test-helper.js'; -import { challengeRepository, releaseRepository } from '../../lib/infrastructure/repositories/index.js'; -import { ChallengeForRelease } from '../../lib/domain/models/release/index.js'; -import * as script from '../../scripts/fix-obsolete-cloned-challenges/index.js'; -import { Challenge } from '../../lib/domain/models/index.js'; - -describe('Script | Fix obsolete cloned challenges', function() { - afterEach(async () => { - await knex('focus_phrase').truncate(); - }); - - it('should revert obsolete challenges with no attachments within a specific script execution to their original statuses', async function() { - // given - const scriptToExect = '123456789'; - await knex('focus_phrase').insert([ - { - id: 1, - createdAt: new Date(), - originPersistantId: 'null', - persistantId: 'challengeNotInScript', - type: 'challenge', - scriptExectId: '789456123', - }, - { - id: 2, - createdAt: new Date(), - originPersistantId: 'null', - persistantId: 'skillIgnored', - type: 'skill', - scriptExectId: scriptToExect, - }, - { - id: 3, - createdAt: new Date(), - originPersistantId: 'null', - persistantId: 'challengeWithAttachmentIllustration', - type: 'challenge', - scriptExectId: scriptToExect, - }, - { - id: 4, - createdAt: new Date(), - originPersistantId: 'null', - persistantId: 'challengeWithAttachmentAtt', - type: 'challenge', - scriptExectId: scriptToExect, - }, - { - id: 5, - createdAt: new Date(), - originPersistantId: 'null', - persistantId: 'challengeA', - type: 'challenge', - scriptExectId: scriptToExect, - }, - { - id: 6, - createdAt: new Date(), - originPersistantId: 'null', - persistantId: 'challengeB', - type: 'challenge', - scriptExectId: scriptToExect, - }, - { - id: 7, - createdAt: new Date(), - originPersistantId: 'null', - persistantId: 'challengeC', - type: 'challenge', - scriptExectId: scriptToExect, - }, - ]); - const challengeAFromRelease = domainBuilder.buildChallengeForRelease({ - id: 'challengeA', - status: ChallengeForRelease.STATUSES.VALIDE, - illustrationUrl: null, - }); - challengeAFromRelease.attachments = undefined; - const challengeBFromRelease = domainBuilder.buildChallengeForRelease({ - id: 'challengeB', - status: ChallengeForRelease.STATUSES.PROPOSE, - illustrationUrl: null, - attachments: [], - }); - const challengeWithIllustration = domainBuilder.buildChallengeForRelease({ - id: 'challengeWithAttachmentIllustration', - status: ChallengeForRelease.STATUSES.VALIDE, - illustrationUrl: 'some attachment url', - attachments: [], - }); - const challengeWithPieceJointe = domainBuilder.buildChallengeForRelease({ - id: 'challengeWithAttachmentAtt', - status: ChallengeForRelease.STATUSES.PROPOSE, - illustrationUrl: null, - attachments: ['piece jointe'], - }); - const release = domainBuilder.buildDomainRelease({ - content: domainBuilder.buildContentForRelease({ - challenges: [ - challengeAFromRelease, - challengeBFromRelease, - challengeWithIllustration, - challengeWithPieceJointe, - ], - }), - }); - - const challengeAOnAirtable = domainBuilder.buildChallenge({ - id: 'challengeA', - status: Challenge.STATUSES.PERIME, - madeObsoleteAt: '2023-04-04T10:47:05.555Z', - files: [], - }); - const challengeBOnAirtable = domainBuilder.buildChallenge({ - id: 'challengeB', - status: Challenge.STATUSES.PERIME, - madeObsoleteAt: '2023-04-04T10:57:05.555Z', - files: [], - }); - const challengeCOnAirtable = domainBuilder.buildChallenge({ - id: 'challengeC', - status: Challenge.STATUSES.PERIME, - madeObsoleteAt: '2023-04-04T10:37:05.555Z', - files: [], - }); - const challengesFromAirtable = [challengeAOnAirtable, challengeBOnAirtable, challengeCOnAirtable]; - vi.spyOn(releaseRepository, 'getRelease').mockResolvedValue(release); - vi.spyOn(challengeRepository, 'get') - .mockImplementation((id) => challengesFromAirtable.find((chal) => chal.id === id)); - vi.spyOn(challengeRepository, 'update') - .mockResolvedValue(true); - - // when - await script.revertObsoleteChallengesToOriginalStatus({ - dryRun: false, - scriptExectIdToFix: scriptToExect, - releaseId: 'someReleaseId', - }); - - // then - expect(releaseRepository.getRelease).toHaveBeenCalledWith('someReleaseId'); - expect(challengeRepository.update).toHaveBeenCalledTimes(2); - expect(challengeRepository.update).toHaveBeenCalledWith(domainBuilder.buildChallenge({ - ...challengeAOnAirtable, - status: Challenge.STATUSES.VALIDE, - madeObsoleteAt: null, - })); - expect(challengeRepository.update).toHaveBeenCalledWith(domainBuilder.buildChallenge({ - ...challengeBOnAirtable, - status: Challenge.STATUSES.PROPOSE, - madeObsoleteAt: null, - })); - }); -}); diff --git a/api/tests/scripts/upload-multi-locales-to-phrase_test.js b/api/tests/scripts/upload-multi-locales-to-phrase_test.js deleted file mode 100644 index 6abf7c0bf..000000000 --- a/api/tests/scripts/upload-multi-locales-to-phrase_test.js +++ /dev/null @@ -1,326 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest'; -import { databaseBuilder, domainBuilder, knex } from '../test-helper.js'; -import { Challenge } from '../../lib/domain/models/index.js'; -import nock from 'nock'; -import multipart from 'parse-multipart-data'; -import { Buffer } from 'node:buffer'; -import { uploadToPhrase } from '../../scripts/upload-multi-locales-to-phrase/index.js'; -import { challengeRepository, releaseRepository, skillRepository } from '../../lib/infrastructure/repositories/index.js'; - -describe('#script.uploadToPhrase',() => { - - afterEach(()=> { - return knex('focus_phrase').truncate(); - }); - - it('should return a super csv', async () => { - // given - const scriptExectId = 'scriptExectId'; - const skill1 = domainBuilder.buildSkill({ - id:'skill1', - tubeId: 'tube1', - name: '@tube1', - hint_i18n: { - fr: 'hint skill1 fr', - nl: 'hint skill1 nl', - } - }); - const skill2 = domainBuilder.buildSkill({ - id:'skill2', - tubeId: 'tube1', - name: '@tube2', - hint_i18n: { - fr: 'hint skill2 fr', - es: 'hint skill2 es', - } - }); - databaseBuilder.factory.buildTranslation({ - key: 'skill.skill1.hint', - locale: 'fr', - value: 'hint skill1 fr' - }); - databaseBuilder.factory.buildTranslation({ - key: 'skill.skill1.hint', - locale: 'nl', - value: 'hint skill1 nl' - }); - databaseBuilder.factory.buildTranslation({ - key: 'skill.skill2.hint', - locale: 'fr', - value: 'hint skill2 fr' - }); - databaseBuilder.factory.buildTranslation({ - key: 'skill.skill2.hint', - locale: 'es', - value: 'hint skill2 es' - }); - const challengeA = domainBuilder.buildChallenge({ - id: 'challengeAID', - skillId: skill1.id, - status: Challenge.STATUSES.VALIDE, - locales: ['fr'], - localizedChallenges: [ - domainBuilder.buildLocalizedChallenge({ - id: 'challengeAID', - challengeId: 'challengeAID', - locale: 'fr', - }), - domainBuilder.buildLocalizedChallenge({ - id: 'challengeA_NL_ID', - challengeId: 'challengeAID', - locale: 'nl', - }), - domainBuilder.buildLocalizedChallenge({ - id: 'challengeA_ES_ID', - challengeId: 'challengeAID', - locale: 'es', - }), - ], - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeAID.instruction', - locale: 'fr', - value: 'challengeAID instruction FR', - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeAID.instruction', - locale: 'es', - value: 'challengeAID instruction ES', - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeAID.instruction', - locale: 'nl', - value: 'challengeAID instruction NL', - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeAID.illustrationAlt', - locale: 'fr', - value: 'challengeAID illustrationAlt FR', - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeAID.illustrationAlt', - locale: 'nl', - value: 'challengeAID illustrationAlt NL', - }); - const challengeB = domainBuilder.buildChallenge({ - id: 'challengeBId', - skillId: skill2.id, - status: Challenge.STATUSES.VALIDE, - locales: ['fr-fr'], - localizedChallenges: [ - domainBuilder.buildLocalizedChallenge({ - id: 'challengeBId', - challengeId: 'challengeBId', - locale: 'fr-fr', - }), - domainBuilder.buildLocalizedChallenge({ - id: 'challengeB_ES_Id', - challengeId: 'challengeBId', - locale: 'jp', - }), - ], - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeBId.instruction', - locale: 'fr-fr', - value: 'challengeBId instruction FRfr', - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeBId.instruction', - locale: 'jp', - value: 'ITADAKISMASU', - }); - const challengeC = domainBuilder.buildChallenge({ - id: 'challengeCId', - skillId: skill2.id, - status: Challenge.STATUSES.VALIDE, - localizedChallenges: [ - domainBuilder.buildLocalizedChallenge({ - id: 'challengeCId', - challengeId: 'challengeCId', - locale: 'fr', - }), - domainBuilder.buildLocalizedChallenge({ - id: 'challengeC_NL_Id', - challengeId: 'challengeCId', - locale: 'nl', - }), - ], - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeCId.instruction', - locale: 'fr', - value: 'challengeCId instruction FR', - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeCId.instruction', - locale: 'nl', - value: 'challengeCId instruction NL', - }); - const challengeD = domainBuilder.buildChallenge({ - id: 'challengeDId', - skillId: skill2.id, - status: Challenge.STATUSES.PROPOSE, - localizedChallenges: [ - domainBuilder.buildLocalizedChallenge({ - id: 'challengeDId', - challengeId: 'challengeDId', - locale: 'fr', - }), - ], - }); - databaseBuilder.factory.buildTranslation({ - key: 'challenge.challengeDId.instruction', - locale: 'fr', - value: 'challengeDId instruction FR', - }); - - await databaseBuilder.commit(); - - await knex('focus_phrase').insert([ - { - type: 'skill', - persistantId: skill1.id, - scriptExectId - }, { - type: 'skill', - persistantId: skill2.id, - scriptExectId - }, { - type: 'challenge', - persistantId: challengeA.id, - scriptExectId - }, { - type: 'challenge', - persistantId: challengeB.id, - scriptExectId - }, { - type: 'challenge', - persistantId: challengeC.id, - scriptExectId - }, { - type: 'challenge', - persistantId: challengeD.id, - scriptExectId - } - ]); - - const releaseChallengeA = domainBuilder.buildChallengeForRelease(challengeA); - const releaseChallengeB = domainBuilder.buildChallengeForRelease(challengeB); - const releaseChallengeC = domainBuilder.buildChallengeForRelease(challengeC); - const releaseChallengeD = domainBuilder.buildChallengeForRelease(challengeD); - const releaseSkill1 = domainBuilder.buildSkillForRelease(skill1); - const releaseSkill2 = domainBuilder.buildSkillForRelease(skill2); - const releaseTube = domainBuilder.buildTubeForRelease({ - id: 'tube1', - competenceId: 'competenceId1', - name: '@tube' - }); - const releaseCompetence = domainBuilder.buildCompetenceForRelease({ - id: 'competenceId1', - areaId: 'areaId1', - index: '1.1' - }); - const releaseArea = domainBuilder.buildAreaForRelease({ - id: 'areaId1', - frameworkId: 'frameworkId1', - code: '1' - }); - const releaseFramework = domainBuilder.buildFrameworkForRelease({ - id: 'frameworkId1', - name: 'pix' - }); - const content = domainBuilder.buildContentForRelease({ - frameworks: [releaseFramework], - areas: [releaseArea], - competences: [releaseCompetence], - tubes: [releaseTube], - skills: [releaseSkill1, releaseSkill2], - challenges: [releaseChallengeA, releaseChallengeB, releaseChallengeC, releaseChallengeD], - }); - const release = domainBuilder.buildDomainRelease({ content }); - vi.spyOn(skillRepository, 'list').mockImplementation(()=> { - return [skill1, skill2]; - }); - vi.spyOn(challengeRepository, 'list').mockImplementation(()=> { - return [challengeA, challengeB, challengeC, challengeD]; - }); - vi.spyOn(releaseRepository, 'create').mockImplementation(() => { - return 'myReleaseID'; - }); - vi.spyOn(releaseRepository, 'getRelease').mockImplementation(() => { - return release; - }); - const phraseLocalesAPI = nock('https://api.phrase.com') - .get('/v2/projects/MY_PHRASE_PROJECT_ID/locales') - .matchHeader('authorization', 'token MY_PHRASE_ACCESS_TOKEN') - .reply(200, [ - { - id: 'frLocaleId', - name: 'fr', - code: 'fr', - default: true, - }, - { - id: 'nlLocaleId', - name: 'nl', - code: 'nl', - default: false, - }, - ]); - - const parseFormData = (body) => { - const boundary = body.match(/.*/g)[0].slice(2); - return multipart.parse(Buffer.from(body), boundary); - }; - const findFormDataParameter = (parsedBody, name) => { - return parsedBody.find((part) => part.name === name); - }; - const matchFormDataParameter = (parsedBody, name, value) => { - return findFormDataParameter(parsedBody, name).data.toString() === value; - }; - - let csvContent; - const phraseUploadAPI = nock('https://api.phrase.com') - .post('/v2/projects/MY_PHRASE_PROJECT_ID/uploads', (body) => { - const parsedBody = parseFormData(body); - csvContent = findFormDataParameter(parsedBody, 'file').data.toString(); - return matchFormDataParameter(parsedBody, 'locale_id', 'frLocaleId') && - matchFormDataParameter(parsedBody, 'file_format', 'csv') && - matchFormDataParameter(parsedBody, 'update_descriptions', 'false') && - matchFormDataParameter(parsedBody, 'update_translations', 'false') && - matchFormDataParameter(parsedBody, 'skip_upload_tags', 'true') && - matchFormDataParameter(parsedBody, 'locale_mapping[es]', '2') && - matchFormDataParameter(parsedBody, 'locale_mapping[fr]', '3') && - matchFormDataParameter(parsedBody, 'locale_mapping[nl]', '4') && - matchFormDataParameter(parsedBody, 'format_options[key_index]', '1') && - matchFormDataParameter(parsedBody, 'format_options[tag_column]', '5') && - matchFormDataParameter(parsedBody, 'format_options[comment_index]', '6') && - matchFormDataParameter(parsedBody, 'format_options[header_content_row]', 'true'); - }) - .matchHeader('authorization', 'token MY_PHRASE_ACCESS_TOKEN') - .reply(201, {}); - - // when - await uploadToPhrase({ scriptExectId }); - - expect(phraseLocalesAPI.isDone()).to.be.true; - expect(phraseUploadAPI.isDone()).to.be.true; - expect(csvContent).toEqual( - `key,es,fr,nl,tags,description -skill.skill1.hint,,hint skill1 fr,hint skill1 nl,"acquis,pix-1-1.1-tube-tube1,pix-1-1.1-tube,pix-1-1.1,pix-1,pix", -skill.skill2.hint,hint skill2 es,hint skill2 fr,,"acquis,pix-1-1.1-tube-tube2,pix-1-1.1-tube,pix-1-1.1,pix-1,pix", -challenge.challengeAID.instruction,challengeAID instruction ES,challengeAID instruction FR,challengeAID instruction NL,"epreuve,pix-1-1.1-tube-tube1-valide,pix-1-1.1-tube-tube1,pix-1-1.1-tube,pix-1-1.1,pix-1,pix","Prévisualisation FR: http://test.site/api/challenges/challengeAID/preview -Prévisualisation ES: http://test.site/api/challenges/challengeAID/preview?locale=es -Prévisualisation NL: http://test.site/api/challenges/challengeAID/preview?locale=nl -Pix Editor: http://test.site/challenge/challengeAID" -challenge.challengeAID.illustrationAlt,,challengeAID illustrationAlt FR,challengeAID illustrationAlt NL,"epreuve,pix-1-1.1-tube-tube1-valide,pix-1-1.1-tube-tube1,pix-1-1.1-tube,pix-1-1.1,pix-1,pix","Prévisualisation FR: http://test.site/api/challenges/challengeAID/preview -Prévisualisation ES: http://test.site/api/challenges/challengeAID/preview?locale=es -Prévisualisation NL: http://test.site/api/challenges/challengeAID/preview?locale=nl -Pix Editor: http://test.site/challenge/challengeAID" -challenge.challengeCId.instruction,,challengeCId instruction FR,challengeCId instruction NL,"epreuve,pix-1-1.1-tube-tube2-valide,pix-1-1.1-tube-tube2,pix-1-1.1-tube,pix-1-1.1,pix-1,pix","Prévisualisation FR: http://test.site/api/challenges/challengeCId/preview -Prévisualisation ES: http://test.site/api/challenges/challengeCId/preview?locale=es -Prévisualisation NL: http://test.site/api/challenges/challengeCId/preview?locale=nl -Pix Editor: http://test.site/challenge/challengeCId"`); - }); -});