first commit

This commit is contained in:
2025-04-24 13:11:28 +08:00
commit ff9c54d5e4
5960 changed files with 834111 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
import { expect } from 'chai'
import { getHueForUserId } from '@/shared/utils/colors'
describe('colors', function () {
const currentUserId = '5bf7dab7a18b0b7a1cf6738c'
beforeEach(function () {
window.metaAttributesCache.set('ol-user_id', currentUserId)
})
describe('getHueForUserId', function () {
it('returns the OWN_HUE for the current user', function () {
expect(getHueForUserId(currentUserId)).to.equal(200)
})
it('returns the ANONYMOUS_HUE for an anonymous user', function () {
expect(getHueForUserId()).to.equal(100)
expect(getHueForUserId('anonymous-user')).to.equal(100)
})
it('generates a hue based on user id', function () {
expect(
getHueForUserId('59ad79f46337430b3d37cb9e', currentUserId)
).to.equal(146)
})
it('shifts the hue away from the OWN_HUE if it is within a threshold', function () {
// Ordinarily, this user id would generate a hue of 183. However, this is
// visually "too close" to the OWN_HUE, meaning that it could be
// misinterpreted. Therefore we shift it away
expect(getHueForUserId('20ad79f46337430b3d37cb9f')).to.equal(323)
})
})
})

View File

@@ -0,0 +1,316 @@
import { expect } from 'chai'
import { formatCurrency } from '../../../../frontend/js/shared/utils/currency'
/*
Users can select any language we support, regardless of the country where they are located.
Which mean that any combination of "supported language"-"supported currency" can be displayed
on the user's screen.
Users located in the USA visiting https://fr.overleaf.com/user/subscription/plans
should see amounts in USD (because of their IP address),
but with French text, number formatting and currency formats (because of language choice).
(e.g. 1 000,00 $)
Users located in the France visiting https://www.overleaf.com/user/subscription/plans
should see amounts in EUR (because of their IP address),
but with English text, number formatting and currency formats (because of language choice).
(e.g. €1,000.00)
*/
describe('formatCurrency', function () {
describe('en', function () {
const format = currency => priceInCents =>
formatCurrency(priceInCents, currency)
describe('USD', function () {
const formatUSD = format('USD')
it('should format basic amounts', function () {
expect(formatUSD(0)).to.equal('$0.00')
expect(formatUSD(12.34)).to.equal('$12.34')
expect(formatUSD(123)).to.equal('$123.00')
})
it('should format thousand separators', function () {
expect(formatUSD(1_000)).to.equal('$1,000.00')
expect(formatUSD(98_765_432.1)).to.equal('$98,765,432.10')
})
it('should format negative amounts', function () {
expect(formatUSD(-0.01)).to.equal('-$0.01')
expect(formatUSD(-12.34)).to.equal('-$12.34')
expect(formatUSD(-123)).to.equal('-$123.00')
})
})
describe('EUR', function () {
const formatEUR = format('EUR')
it('should format basic amounts', function () {
expect(formatEUR(0)).to.equal('€0.00')
expect(formatEUR(12.34)).to.equal('€12.34')
expect(formatEUR(123)).to.equal('€123.00')
})
it('should format thousand separators', function () {
expect(formatEUR(1_000)).to.equal('€1,000.00')
expect(formatEUR(98_765_432.1)).to.equal('€98,765,432.10')
})
it('should format negative amounts', function () {
expect(formatEUR(-0.01)).to.equal('-€0.01')
expect(formatEUR(-12.34)).to.equal('-€12.34')
expect(formatEUR(-123)).to.equal('-€123.00')
})
})
describe('HUF', function () {
const formatHUF = format('HUF')
it('should format basic amounts', function () {
expect(formatHUF(0)).to.equal('Ft 0.00')
expect(formatHUF(12.34)).to.equal('Ft 12.34')
expect(formatHUF(123)).to.equal('Ft 123.00')
})
it('should format thousand separators', function () {
expect(formatHUF(1_000)).to.equal('Ft 1,000.00')
expect(formatHUF(98_765_432.1)).to.equal('Ft 98,765,432.10')
})
it('should format negative amounts', function () {
expect(formatHUF(-0.01)).to.equal('-Ft 0.01')
expect(formatHUF(-12.34)).to.equal('-Ft 12.34')
expect(formatHUF(-123)).to.equal('-Ft 123.00')
})
})
describe('CLP', function () {
const formatCLP = format('CLP')
it('should format basic amounts', function () {
expect(formatCLP(0)).to.equal('$0')
expect(formatCLP(12.34)).to.equal('$12')
expect(formatCLP(123)).to.equal('$123')
expect(formatCLP(1234)).to.equal('$1,234')
})
it('should format thousand separators', function () {
expect(formatCLP(1_000)).to.equal('$1,000')
expect(formatCLP(98_765_432.1)).to.equal('$98,765,432')
})
it('should format negative amounts', function () {
expect(formatCLP(-1)).to.equal('-$1')
expect(formatCLP(-12.34)).to.equal('-$12')
expect(formatCLP(-1234)).to.equal('-$1,234')
})
})
describe('all currencies', function () {
it('should format 1 "minimal atomic units"', function () {
const amount = 1
// "no cents currencies"
expect(format('CLP')(amount)).to.equal('$1')
expect(format('JPY')(amount)).to.equal('¥1')
expect(format('KRW')(amount)).to.equal('₩1')
expect(format('VND')(amount)).to.equal('₫1')
// other currencies
expect(format('AUD')(amount)).to.equal('$1.00')
expect(format('BRL')(amount)).to.equal('R$1.00')
expect(format('CAD')(amount)).to.equal('$1.00')
expect(format('CHF')(amount)).to.equal('CHF 1.00')
expect(format('CNY')(amount)).to.equal('¥1.00')
expect(format('COP')(amount)).to.equal('$1.00')
expect(format('DKK')(amount)).to.equal('kr 1.00')
expect(format('EUR')(amount)).to.equal('€1.00')
expect(format('GBP')(amount)).to.equal('£1.00')
expect(format('HUF')(amount)).to.equal('Ft 1.00')
expect(format('IDR')(amount)).to.equal('Rp 1.00')
expect(format('INR')(amount)).to.equal('₹1.00')
expect(format('MXN')(amount)).to.equal('$1.00')
expect(format('MYR')(amount)).to.equal('RM 1.00')
expect(format('NOK')(amount)).to.equal('kr 1.00')
expect(format('NZD')(amount)).to.equal('$1.00')
expect(format('PEN')(amount)).to.equal('PEN 1.00')
expect(format('PHP')(amount)).to.equal('₱1.00')
expect(format('SEK')(amount)).to.equal('kr 1.00')
expect(format('SGD')(amount)).to.equal('$1.00')
expect(format('THB')(amount)).to.equal('฿1.00')
expect(format('USD')(amount)).to.equal('$1.00')
})
it('should format 1_234_567.897_654 "minimal atomic units"', function () {
const amount = 1_234_567.897_654
// "no cents currencies"
expect(format('CLP')(amount)).to.equal('$1,234,568')
expect(format('JPY')(amount)).to.equal('¥1,234,568')
expect(format('KRW')(amount)).to.equal('₩1,234,568')
expect(format('VND')(amount)).to.equal('₫1,234,568')
// other currencies
expect(format('AUD')(amount)).to.equal('$1,234,567.90')
expect(format('BRL')(amount)).to.equal('R$1,234,567.90')
expect(format('CAD')(amount)).to.equal('$1,234,567.90')
expect(format('CHF')(amount)).to.equal('CHF 1,234,567.90')
expect(format('CNY')(amount)).to.equal('¥1,234,567.90')
expect(format('COP')(amount)).to.equal('$1,234,567.90')
expect(format('DKK')(amount)).to.equal('kr 1,234,567.90')
expect(format('EUR')(amount)).to.equal('€1,234,567.90')
expect(format('GBP')(amount)).to.equal('£1,234,567.90')
expect(format('HUF')(amount)).to.equal('Ft 1,234,567.90')
expect(format('IDR')(amount)).to.equal('Rp 1,234,567.90')
expect(format('INR')(amount)).to.equal('₹1,234,567.90')
expect(format('MXN')(amount)).to.equal('$1,234,567.90')
expect(format('MYR')(amount)).to.equal('RM 1,234,567.90')
expect(format('NOK')(amount)).to.equal('kr 1,234,567.90')
expect(format('NZD')(amount)).to.equal('$1,234,567.90')
expect(format('PEN')(amount)).to.equal('PEN 1,234,567.90')
expect(format('PHP')(amount)).to.equal('₱1,234,567.90')
expect(format('SEK')(amount)).to.equal('kr 1,234,567.90')
expect(format('SGD')(amount)).to.equal('$1,234,567.90')
expect(format('THB')(amount)).to.equal('฿1,234,567.90')
expect(format('USD')(amount)).to.equal('$1,234,567.90')
})
})
})
describe('fr', function () {
const format = currency => priceInCents =>
formatCurrency(priceInCents, currency, 'fr')
describe('USD', function () {
const formatUSD = format('USD')
it('should format basic amounts', function () {
expect(formatUSD(0)).to.equal('0,00 $')
expect(formatUSD(12.34)).to.equal('12,34 $')
expect(formatUSD(123)).to.equal('123,00 $')
})
it('should format thousand separators', function () {
expect(formatUSD(1_000)).to.equal('1000,00 $')
expect(formatUSD(98_765_432.1)).to.equal('98765432,10 $')
})
it('should format negative amounts', function () {
expect(formatUSD(-0.01)).to.equal('-0,01 $')
expect(formatUSD(-12.34)).to.equal('-12,34 $')
expect(formatUSD(-123)).to.equal('-123,00 $')
})
})
describe('EUR', function () {
const formatEUR = format('EUR')
it('should format basic amounts', function () {
expect(formatEUR(0)).to.equal('0,00 €')
expect(formatEUR(12.34)).to.equal('12,34 €')
expect(formatEUR(123)).to.equal('123,00 €')
})
it('should format thousand separators', function () {
expect(formatEUR(1_000)).to.equal('1000,00 €')
expect(formatEUR(98_765_432.1)).to.equal('98765432,10 €')
})
it('should format negative amounts', function () {
expect(formatEUR(-0.01)).to.equal('-0,01 €')
expect(formatEUR(-12.34)).to.equal('-12,34 €')
expect(formatEUR(-123)).to.equal('-123,00 €')
})
})
describe('HUF', function () {
const formatHUF = format('HUF')
it('should format basic amounts', function () {
expect(formatHUF(0)).to.equal('0,00 Ft')
expect(formatHUF(12.34)).to.equal('12,34 Ft')
expect(formatHUF(123)).to.equal('123,00 Ft')
})
it('should format thousand separators', function () {
expect(formatHUF(1_000)).to.equal('1000,00 Ft')
expect(formatHUF(98_765_432.1)).to.equal('98765432,10 Ft')
})
it('should format negative amounts', function () {
expect(formatHUF(-0.01)).to.equal('-0,01 Ft')
expect(formatHUF(-12.34)).to.equal('-12,34 Ft')
expect(formatHUF(-123)).to.equal('-123,00 Ft')
})
})
describe('CLP', function () {
const formatCLP = format('CLP')
it('should format basic amounts', function () {
expect(formatCLP(0)).to.equal('0 $')
expect(formatCLP(12.34)).to.equal('12 $')
expect(formatCLP(123)).to.equal('123 $')
expect(formatCLP(1234)).to.equal('1234 $')
})
it('should format thousand separators', function () {
expect(formatCLP(100_000)).to.equal('100000 $')
expect(formatCLP(9_876_543_210)).to.equal('9876543210 $')
})
it('should format negative amounts', function () {
expect(formatCLP(-1)).to.equal('-1 $')
expect(formatCLP(-12.34)).to.equal('-12 $')
expect(formatCLP(-1234)).to.equal('-1234 $')
})
})
describe('all currencies', function () {
it('should format 1 "minimal atomic units"', function () {
const amount = 1
// "no cents currencies"
expect(format('CLP')(amount)).to.equal('1 $')
expect(format('JPY')(amount)).to.equal('1 ¥')
expect(format('KRW')(amount)).to.equal('1 ₩')
expect(format('VND')(amount)).to.equal('1 ₫')
// other currencies
expect(format('AUD')(amount)).to.equal('1,00 $')
expect(format('BRL')(amount)).to.equal('1,00 R$')
expect(format('CAD')(amount)).to.equal('1,00 $')
expect(format('CHF')(amount)).to.equal('1,00 CHF')
expect(format('CNY')(amount)).to.equal('1,00 ¥')
expect(format('COP')(amount)).to.equal('1,00 $')
expect(format('EUR')(amount)).to.equal('1,00 €')
expect(format('GBP')(amount)).to.equal('1,00 £')
expect(format('USD')(amount)).to.equal('1,00 $')
})
it('should format 1_234_567.897_654 "minimal atomic units"', function () {
const amount = 1_234_567.897_654
// "no cents currencies"
expect(format('CLP')(amount)).to.equal('1234568 $')
expect(format('JPY')(amount)).to.equal('1234568 ¥')
expect(format('KRW')(amount)).to.equal('1234568 ₩')
expect(format('VND')(amount)).to.equal('1234568 ₫')
// other currencies
expect(format('AUD')(amount)).to.equal('1234567,90 $')
expect(format('BRL')(amount)).to.equal('1234567,90 R$')
expect(format('CAD')(amount)).to.equal('1234567,90 $')
expect(format('CHF')(amount)).to.equal('1234567,90 CHF')
expect(format('CNY')(amount)).to.equal('1234567,90 ¥')
expect(format('COP')(amount)).to.equal('1234567,90 $')
expect(format('EUR')(amount)).to.equal('1234567,90 €')
expect(format('GBP')(amount)).to.equal('1234567,90 £')
expect(format('USD')(amount)).to.equal('1234567,90 $')
})
})
})
})

View File

@@ -0,0 +1,46 @@
import { expect } from 'chai'
import { isValidEmail } from '../../../../frontend/js/shared/utils/email'
const validEmailAddresses = [
'email@example.com',
'firstname.lastname@example.com',
'firstname-lastname@example.com',
'email@subdomain.example.com',
'firstname+lastname@example.com',
'1234567890@example.com',
'email@example-one.com',
'_@example.com',
'email@example.name',
'email@example.co.jp',
]
const invalidEmailAddresses = [
'plaintext',
'#@%^%#$@#$@#.com',
'@example.com',
'email.example.com',
'.email@example.com',
'email.@example.com',
'email..email@example.com',
'email@example.com (Joe Smith)',
'email@example',
'email@111.222.333.44444',
'email@example..com',
]
describe('isValidEmail', function () {
it('should return true for valid email addresses', function () {
validEmailAddresses.forEach(email =>
expect(isValidEmail(email)).to.equal(true, email + ' should be valid ')
)
})
it('should return false for invalid email addresses', function () {
invalidEmailAddresses.forEach(email =>
expect(isValidEmail(email)).to.equal(
false,
email + ' should not be valid '
)
)
})
})

View File

@@ -0,0 +1,19 @@
import { expect } from 'chai'
import { generateMD5Hash } from '@/shared/utils/md5'
describe('md5', function () {
describe('generateSHA1Hash', function () {
it('sample string 1', function () {
expect(generateMD5Hash('sample string 1')).to.equal(
'b7988250a49c21459260b41d2b435dae'
)
})
it('sample string 2', function () {
expect(generateMD5Hash('sample string 2')).to.equal(
'371b9c84c640a9e121523156aeae4958'
)
})
})
})

View File

@@ -0,0 +1,79 @@
import { expect } from 'chai'
import { generateSHA1Hash } from '../../../../frontend/js/shared/utils/sha1'
import crypto from 'node:crypto'
function generateSHA1HashNode(content) {
return crypto.createHash('sha1').update(content, 'utf8').digest('hex')
}
function generateRandomUnicodeString(length) {
let result = ''
for (let i = 0; i < length; i++) {
const range = [0x0000, 0x10ffff]
const codePoint =
Math.floor(Math.random() * (range[1] - range[0] + 1)) + range[0]
result += String.fromCharCode(codePoint)
}
return result
}
function generateMultipleRandomStrings(numStrings, maxLength) {
const randomStrings = []
for (let i = 0; i < numStrings; i++) {
const length = Math.floor(Math.random() * maxLength)
randomStrings.push(generateRandomUnicodeString(length))
}
return [...new Set(randomStrings)]
}
describe('sha1', function () {
describe('generateSHA1Hash', function () {
const randomStrings = generateMultipleRandomStrings(100, 1000)
it('verify 100 random strings', function () {
for (const str of randomStrings) {
expect(generateSHA1Hash(str)).to.equal(generateSHA1HashNode(str))
}
})
it('sample string 1', function () {
expect(generateSHA1Hash('sample string 1')).to.equal(
'135028161629af5901ea2f15554730dc0de38a01'
)
})
it('sample string 2', function () {
expect(generateSHA1Hash('sample string 2')).to.equal(
'db9460374e49a7c737b609c2fb37302381f345d6'
)
})
it('abc', function () {
expect(generateSHA1Hash('abc')).to.equal(
'a9993e364706816aba3e25717850c26c9cd0d89d'
)
})
it('generates a sha1 for an empty string', function () {
expect(generateSHA1Hash('')).to.equal(
'da39a3ee5e6b4b0d3255bfef95601890afd80709'
)
})
it('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', function () {
expect(
generateSHA1Hash(
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'
)
).to.equal('84983e441c3bd26ebaae4aa1f95129e5e54670f1')
})
it('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', function () {
expect(
generateSHA1Hash(
'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'
)
).to.equal('a49b2446a02c645bf419f995b67091253a04a259')
})
})
})

View File

@@ -0,0 +1,45 @@
import { expect } from 'chai'
import { cleanURL } from '@/shared/utils/url-helper'
describe('url-helper', function () {
describe('cleanURL', function () {
describe('without mode', function () {
it('removes trailing slash', function () {
const url = new URL('https://www.ovelreaf.com/project/1abc/')
expect(cleanURL(url).href).to.equal(
'https://www.ovelreaf.com/project/1abc'
)
})
it('clears the mode from the detached URL', function () {
const url = new URL('https://www.ovelreaf.com/project/2abc/detached')
expect(cleanURL(url).href).to.equal(
'https://www.ovelreaf.com/project/2abc'
)
})
it('clears the mode from the detacher URL', function () {
const url = new URL('https://www.ovelreaf.com/project/2abc/detacher/')
expect(cleanURL(url).href).to.equal(
'https://www.ovelreaf.com/project/2abc'
)
})
})
describe('with mode', function () {
it('handles with trailing slash', function () {
const url = new URL('https://www.ovelreaf.com/project/3abc/')
expect(cleanURL(url, 'detacher').href).to.equal(
'https://www.ovelreaf.com/project/3abc/detacher'
)
})
it('handles without trailing slash', function () {
const url = new URL('https://www.ovelreaf.com/project/4abc')
expect(cleanURL(url, 'detached').href).to.equal(
'https://www.ovelreaf.com/project/4abc/detached'
)
})
})
})
})