Skip to content

Commit

Permalink
Merge branch 'zammad:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
boie0025 authored Nov 28, 2023
2 parents 8c19277 + 118c19e commit 8980135
Show file tree
Hide file tree
Showing 8,104 changed files with 1,522,903 additions and 179,737 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
57 changes: 14 additions & 43 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -1,44 +1,15 @@
---
engines:
brakeman:
enabled: true
bundler-audit:
enabled: true
csslint:
enabled: true
coffeelint:
enabled: true
duplication:
enabled: true
config:
languages:
- ruby
- javascript
eslint:
enabled: true
fixme:
enabled: true
phpmd:
enabled: false
rubocop:
enabled: true
ratings:
paths:
- Gemfile.lock
- "**.erb"
- "**.haml"
- "**.rb"
- "**.rhtml"
- "**.slim"
- "**.css"
- "**.coffee"
- "**.inc"
- "**.js"
- "**.jsx"
- "**.module"
exclude_paths:
- config/
- db/
- script/
- test/
- vendor/
version: "2"
exclude_patterns:
# Bundled thirdparty asset files
- "app/assets/javascripts/app/lib/**/*.js"
- "config/"
- "db/"
- "**/node_modules/"
- "script/"
- "public/assets/"
- "**/spec/"
- "**/test/"
- "**/tests/"
- "**/vendor/"
- "**/*.d.ts"
92 changes: 92 additions & 0 deletions .coffeelint/rules/detect_translatable_string.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
module.exports = class DetectTranslatableString

# coffeelint: disable=detect_translatable_string
rule:
name: 'detect_translatable_string'
level: 'ignore'
message: 'The following string looks like it should be marked as translatable via __(...)'
description: '''
'''

constructor: ->
@callTokens = []

tokens: ['STRING', 'CALL_START', 'CALL_END']

lintToken: (token, tokenApi) ->
[type, tokenValue] = token

if type in ['CALL_START', 'CALL_END']
@trackCall token, tokenApi
return

return false if @isInIgnoredMethod()

return @lintString(token, tokenApi)

lintString: (token, tokenApi) ->
[type, tokenValue] = token

# Remove quotes.
string = tokenValue[1..-2]

# Ignore strings with less than two words.
return false if string.split(' ').length < 2

# Ignore strings that are being used as exception; unlike Ruby exceptions, these should not reach the user.
return false if tokenApi.peek(-3)[1] == 'throw'
return false if tokenApi.peek(-2)[1] == 'throw'
return false if tokenApi.peek(-1)[1] == 'throw'

# Ignore strings that are being used for comparison
return false if tokenApi.peek(-1)[1] == '=='

# String interpolation is handled via concatenation, ignore such strings.
return false if tokenApi.peek(1)[1] == '+'
return false if tokenApi.peek(2)[1] == '+'

BLOCKLIST = [
# Only look at strings starting with upper case letters
/^[^A-Z]/,
# # Ignore strings starting with three upper case letters like SELECT, POST etc.
# /^[A-Z]{3}/,
]

return false if BLOCKLIST.some (entry) ->
#console.log([string, entry, string.match(entry), token, tokenApi.peek(-1), tokenApi.peek(1)])
string.match(entry)

# console.log(tokenApi.peek(-3))
# console.log(tokenApi.peek(-2))
# console.log(tokenApi.peek(-1))
# console.log(token)

return { context: "Found: #{token[1]}" }

ignoredMethods: {
'__': true,
'log': true,
'T': true,
'controllerBind': true,
'debug': true, # App.Log.debug
'error': true, # App.Log.error
'set': true, # App.Config.set
'translateInline': true,
'translateContent': true,
'translatePlain': true,
}

isInIgnoredMethod: ->
#console.log(@callTokens)
for t in @callTokens
return true if t.isIgnoredMethod
return false

trackCall: (token, tokenApi) ->
if token[0] is 'CALL_START'
p = tokenApi.peek(-1)
token.isIgnoredMethod = p and @ignoredMethods[p[1]]
@callTokens.push(token)
else
@callTokens.pop()
return null
2 changes: 0 additions & 2 deletions .csslintrc

This file was deleted.

84 changes: 84 additions & 0 deletions .cypress/cypress.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { defineConfig } from 'cypress'
import { rm } from 'node:fs/promises'
import { resolve, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import { initPlugin as initVisualRegressionPlugin } from '@frsource/cypress-plugin-visual-regression-diff/plugins'
import pkg from '../package.json' assert { type: 'json' }

const dir = dirname(fileURLToPath(import.meta.url))

const isCYCI = !process.env.CY_OPEN
const root = resolve(dir, '..')

// we don't need to optimize graphql and apollo
const skipDeps = ['graphql', 'apollo', '@tiptap/pm']

export default defineConfig({
videosFolder: '.cypress/videos',
supportFolder: '.cypress/support/index.js',
fixturesFolder: '.cypress/fixtures',
downloadsFolder: '.cypress/downloads',
screenshotsFolder: '.cypress/screenshots',
videoCompression: false,
env: {
CY_CI: isCYCI,
pluginVisualRegressionDiffConfig: {
threshold: 0.02,
},
pluginVisualRegressionMaxDiffThreshold: 0.02,
},
component: {
supportFile: '.cypress/support/index.js',
setupNodeEvents(on, config) {
on('after:spec', (spec, results) => {
if (results && results.stats.failures === 0 && results.video) {
return rm(results.video)
}
})
initVisualRegressionPlugin(on, config)
on('before:browser:launch', (browser, launchOptions) => {
if (browser?.family === 'chromium' && browser?.name !== 'electron') {
launchOptions.args.push('--force-device-scale-factor=2')
}
return launchOptions
})
},
devServer: {
framework: 'vue',
bundler: 'vite',
viteConfig: {
mode: 'cypress',
root,
configFile: resolve(dir, '..', 'vite.config.mjs'),
cacheDir: resolve(dir, 'node_modules', '.vite'),
server: {
fs: {
strict: false,
},
hmr: true,
...(isCYCI && { watch: { ignored: ['**/*'] } }),
},
optimizeDeps: {
entries: [
'**/cypress/**/*.cy.ts',
'!**/node_modules/**',
'!**/*.d.ts',
],
include: [
// if you see cypress failing on some dependency, add it to skipDeps
...Object.keys(pkg.dependencies).filter(
(name) => !skipDeps.some((dep) => name.includes(dep)),
),
],
},
},
},
// iPhone 12 viewport
viewportWidth: 390,
viewportHeight: 844,
fileServerFolder: '..',
indexHtmlFile: '.cypress/support/component-index.html',
specPattern: ['app/frontend/cypress/**/*.cy.{js,jsx,ts,tsx}'],
},
retries: 0,
})
5 changes: 5 additions & 0 deletions .cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "[email protected]",
"body": "Fixtures are a great way to mock data for responses to routes"
}
Binary file added .cypress/fixtures/example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions .cypress/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"private": true,
"type": "module",
"devDependencies": {
"@frsource/cypress-plugin-visual-regression-diff": "^2.3.12",
"@testing-library/cypress": "^10.0.1",
"cypress": "^12.17.4",
"cypress-real-events": "^1.11.0"
},
"imports": {
"#tests/*": "../app/frontend/tests/*",
"#shared/*": "../app/frontend/shared/*",
"#mobile/*": "../app/frontend/apps/mobile/*",
"#cy/*": "./*"
}
}
74 changes: 74 additions & 0 deletions .cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/

import '@testing-library/cypress/add-commands'
import 'cypress-real-events/support'
import '@frsource/cypress-plugin-visual-regression-diff'

import { configure } from '@testing-library/cypress'
import { mount } from 'cypress/vue'

configure({ testIdAttribute: 'data-test-id' })

Cypress.Commands.add('mount', mount)

/**
* Simulates a paste event.
* Modified from https://gist.github.com/nickytonline/bcdef8ef00211b0faf7c7c0e7777aaf6
*
* @param subject A jQuery context representing a DOM element.
* @param pasteOptions Set of options for a simulated paste event.
* @param pasteOptions.pastePayload Simulated data that is on the clipboard.
* @param pasteOptions.pasteFormat The format of the simulated paste payload. Default value is 'text'.
* @param pasteOptions.files A list of assisiated file, if any
*
* @returns The subject parameter.
*
* @example
* cy.get('body').paste({
* pasteType: 'application/json',
* pastePayload: {hello: 'yolo'},
* });
*/
Cypress.Commands.add(
'paste',
{ prevSubject: true },
function onPaste(subject, pasteOptions) {
const { pastePayload = '', pasteType = 'text', files = [] } = pasteOptions
const data =
pasteType === 'application/json'
? JSON.stringify(pastePayload)
: pastePayload
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer
const clipboardData = new DataTransfer()
clipboardData.setData(pasteType, data)
files.forEach((file) => {
clipboardData.items.add(file)
})
// https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event
const pasteEvent = new ClipboardEvent('paste', {
bubbles: true,
cancelable: true,
dataType: pasteType,
data,
clipboardData,
})
subject[0].dispatchEvent(pasteEvent)

return subject
},
)

Cypress.Commands.add(
'selectText',
{ prevSubject: true },
(subject, direction, size) => {
return cy
.wrap(subject)
.realPress([
'Shift',
...new Array(size).fill(
direction === 'right' ? 'ArrowRight' : 'ArrowLeft',
),
])
},
)
21 changes: 21 additions & 0 deletions .cypress/support/component-index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html dir="ltr" lang="en-gb">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="stylesheet" href="/assets/mobile/fonts.css">
<title>Zammad</title>
</head>
<style>
body,
html,
#loading-app,
[data-cy-root] {
height: 100%;
}
</style>
<body class="bg-black font-sans text-sm text-white antialiased">
<div data-cy-root></div>
</body>
</html>
21 changes: 21 additions & 0 deletions .cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/

import './prepare.js'

import '#mobile/styles/main.scss'
import '#shared/components/CommonIcon/injectIcons.ts'

import './commands.js'

// @testing-library/cypress uses env to display errors
globalThis.process.env = {
DEBUG_PRINT_LIMIT: 5000,
}

Cypress.Screenshot.defaults({ capture: 'viewport' })

if (Cypress.env('CY_CI')) {
Cypress.config('defaultCommandTimeout', 20000)
}

beforeEach(() => document.fonts.ready)
4 changes: 4 additions & 0 deletions .cypress/support/prepare.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/

// eslint-disable-next-line no-underscore-dangle
window.__ = (str) => str
Loading

0 comments on commit 8980135

Please sign in to comment.