alchemy_cms 7.0.0.pre.b → 7.0.0.pre.c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of alchemy_cms might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/lint.yml +21 -1
- data/.github/workflows/{ci.yml → test.yml} +1 -1
- data/.gitignore +0 -5
- data/CHANGELOG.md +4 -0
- data/Gemfile +0 -1
- data/README.md +3 -3
- data/Rakefile +0 -19
- data/alchemy_cms.gemspec +2 -1
- data/app/assets/config/alchemy_manifest.js +1 -0
- data/app/assets/javascripts/alchemy/admin.js +0 -1
- data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +5 -12
- data/app/assets/stylesheets/alchemy/base.scss +2 -2
- data/app/controllers/alchemy/base_controller.rb +0 -7
- data/{package/src → app/javascript/alchemy_admin}/node_tree.js +2 -2
- data/{package/src → app/javascript/alchemy_admin}/page_publication_fields.js +1 -1
- data/{package/src → app/javascript/alchemy_admin}/page_sorter.js +1 -1
- data/{package/src → app/javascript/alchemy_admin}/picture_editors.js +2 -2
- data/{package/src → app/javascript/alchemy_admin}/sitemap.js +4 -4
- data/app/javascript/alchemy_admin.js +34 -0
- data/app/views/alchemy/_menubar.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/_replace_button.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -1
- data/app/views/alchemy/admin/nodes/index.html.erb +4 -2
- data/app/views/alchemy/admin/pages/_page_layout_filter.html.erb +1 -1
- data/app/views/alchemy/admin/pages/edit.html.erb +3 -4
- data/app/views/alchemy/admin/pages/index.html.erb +1 -1
- data/app/views/alchemy/admin/pages/update.js.erb +2 -2
- data/app/views/alchemy/admin/resources/_filter_bar.html.erb +1 -1
- data/app/views/alchemy/admin/styleguide/index.html.erb +1 -1
- data/app/views/alchemy/admin/uploader/_button.html.erb +1 -1
- data/app/views/alchemy/base/permission_denied.js.erb +1 -1
- data/app/views/alchemy/base/redirect.js.erb +1 -1
- data/app/views/layouts/alchemy/admin.html.erb +4 -8
- data/bin/importmap +4 -0
- data/bin/setup +0 -9
- data/bin/start +1 -1
- data/config/brakeman.ignore +0 -46
- data/config/importmap.rb +8 -0
- data/lib/alchemy/engine.rb +14 -0
- data/lib/alchemy/upgrader/seven_point_zero.rb +13 -23
- data/lib/alchemy/upgrader.rb +0 -11
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +5 -0
- data/lib/alchemy_cms.rb +2 -1
- data/lib/generators/alchemy/install/files/application.html.erb +2 -2
- data/lib/generators/alchemy/install/install_generator.rb +0 -24
- data/lib/tasks/alchemy/upgrade.rake +6 -12
- data/package.json +6 -26
- metadata +44 -27
- data/package/admin.js +0 -34
- data/package/dist/admin.js +0 -16
- data/package/dist/admin.js.map +0 -7
- data/package/src/__tests__/i18n.spec.js +0 -93
- data/package/src/utils/__tests__/ajax.spec.js +0 -168
- data/package/src/utils/__tests__/events.spec.js +0 -38
- /data/{package/src → app/javascript/alchemy_admin}/datepicker.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/file_editors.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/i18n.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/image_cropper.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/image_loader.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/ingredient_anchor_link.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/tinymce.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/translations.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/utils/ajax.js +0 -0
- /data/{package/src → app/javascript/alchemy_admin}/utils/events.js +0 -0
@@ -1,93 +0,0 @@
|
|
1
|
-
import translate from "../i18n"
|
2
|
-
|
3
|
-
describe("translate", () => {
|
4
|
-
describe("if Alchemy.locale is not set", () => {
|
5
|
-
it("Throws an error", () => {
|
6
|
-
expect(() => {
|
7
|
-
translate("help")
|
8
|
-
}).toThrow("Alchemy.locale is not set")
|
9
|
-
})
|
10
|
-
})
|
11
|
-
|
12
|
-
describe("if Alchemy.locale is set to a known locale", () => {
|
13
|
-
beforeEach(() => {
|
14
|
-
Alchemy.locale = "en"
|
15
|
-
})
|
16
|
-
|
17
|
-
describe("if translation is present", () => {
|
18
|
-
beforeEach(() => {
|
19
|
-
Alchemy.translations = { en: { help: "Help" } }
|
20
|
-
})
|
21
|
-
|
22
|
-
it("Returns translated string", () => {
|
23
|
-
expect(translate("help")).toEqual("Help")
|
24
|
-
})
|
25
|
-
|
26
|
-
describe("if key includes a period", () => {
|
27
|
-
describe("that is translated", () => {
|
28
|
-
beforeEach(() => {
|
29
|
-
Alchemy.translations = { en: { formats: { date: "Y-m-d" } } }
|
30
|
-
})
|
31
|
-
|
32
|
-
it("splits into group", () => {
|
33
|
-
expect(translate("formats.date")).toEqual("Y-m-d")
|
34
|
-
})
|
35
|
-
})
|
36
|
-
|
37
|
-
describe("that is not translated", () => {
|
38
|
-
it("returns key", () => {
|
39
|
-
expect(translate("formats.lala")).toEqual("formats.lala")
|
40
|
-
})
|
41
|
-
})
|
42
|
-
|
43
|
-
describe("that has unknown group", () => {
|
44
|
-
it("returns key", () => {
|
45
|
-
expect(translate("foo.bar")).toEqual("foo.bar")
|
46
|
-
})
|
47
|
-
})
|
48
|
-
})
|
49
|
-
|
50
|
-
describe("if replacement is given", () => {
|
51
|
-
beforeEach(() => {
|
52
|
-
Alchemy.translations = { en: { allowed_chars: "of %{number} chars" } }
|
53
|
-
})
|
54
|
-
|
55
|
-
it("replaces it", () => {
|
56
|
-
expect(translate("allowed_chars", 5)).toEqual("of 5 chars")
|
57
|
-
})
|
58
|
-
})
|
59
|
-
})
|
60
|
-
|
61
|
-
describe("if translation is not present", () => {
|
62
|
-
it("Returns passed string", () => {
|
63
|
-
expect(translate("foo")).toEqual("foo")
|
64
|
-
})
|
65
|
-
})
|
66
|
-
})
|
67
|
-
|
68
|
-
describe("if Alchemy.locale is set to a unknown locale", () => {
|
69
|
-
beforeEach(() => {
|
70
|
-
Alchemy.locale = "kl"
|
71
|
-
})
|
72
|
-
|
73
|
-
it("Returns passed string and logs a warning", () => {
|
74
|
-
const spy = jest.spyOn(console, "warn").mockImplementation(() => {})
|
75
|
-
expect(translate("help")).toEqual("help")
|
76
|
-
expect(spy.mock.calls).toEqual([
|
77
|
-
["Translations for locale kl not found!"]
|
78
|
-
])
|
79
|
-
spy.mockRestore()
|
80
|
-
})
|
81
|
-
})
|
82
|
-
|
83
|
-
describe("if Alchemy.translations is not set", () => {
|
84
|
-
it("Returns passed string and logs a warning", () => {
|
85
|
-
const spy = jest.spyOn(console, "warn").mockImplementation(() => {})
|
86
|
-
expect(translate("help")).toEqual("help")
|
87
|
-
expect(spy.mock.calls).toEqual([
|
88
|
-
["Translations for locale kl not found!"]
|
89
|
-
])
|
90
|
-
spy.mockRestore()
|
91
|
-
})
|
92
|
-
})
|
93
|
-
})
|
@@ -1,168 +0,0 @@
|
|
1
|
-
import xhrMock from "xhr-mock"
|
2
|
-
import { get, patch, post } from "../ajax"
|
3
|
-
|
4
|
-
const token = "s3cr3t"
|
5
|
-
|
6
|
-
beforeEach(() => {
|
7
|
-
document.head.innerHTML = `<meta name="csrf-token" content="${token}">`
|
8
|
-
xhrMock.setup()
|
9
|
-
})
|
10
|
-
|
11
|
-
describe("get", () => {
|
12
|
-
it("sends X-CSRF-TOKEN header", async () => {
|
13
|
-
xhrMock.get("http://localhost/users", (req, res) => {
|
14
|
-
expect(req.header("X-CSRF-TOKEN")).toEqual(token)
|
15
|
-
return res.status(200).body('{"message":"Ok"}')
|
16
|
-
})
|
17
|
-
await get("/users")
|
18
|
-
})
|
19
|
-
|
20
|
-
it("sends Content-Type header", async () => {
|
21
|
-
xhrMock.get("http://localhost/users", (req, res) => {
|
22
|
-
expect(req.header("Content-Type")).toEqual(
|
23
|
-
"application/json; charset=utf-8"
|
24
|
-
)
|
25
|
-
return res.status(200).body('{"message":"Ok"}')
|
26
|
-
})
|
27
|
-
await get("/users")
|
28
|
-
})
|
29
|
-
|
30
|
-
it("sends Accept header", async () => {
|
31
|
-
xhrMock.get("http://localhost/users", (req, res) => {
|
32
|
-
expect(req.header("Accept")).toEqual("application/json")
|
33
|
-
return res.status(200).body('{"message":"Ok"}')
|
34
|
-
})
|
35
|
-
await get("/users")
|
36
|
-
})
|
37
|
-
|
38
|
-
it("returns JSON", async () => {
|
39
|
-
xhrMock.get("http://localhost/users", (_req, res) => {
|
40
|
-
return res.status(200).body('{"email":"mail@example.com"}')
|
41
|
-
})
|
42
|
-
await get("/users").then((res) => {
|
43
|
-
expect(res.data).toEqual({ email: "mail@example.com" })
|
44
|
-
})
|
45
|
-
})
|
46
|
-
|
47
|
-
it("JSON parse errors get rejected", async () => {
|
48
|
-
xhrMock.get("http://localhost/users", (_req, res) => {
|
49
|
-
return res.status(200).body('email => "mail@example.com"')
|
50
|
-
})
|
51
|
-
expect.assertions(1)
|
52
|
-
await get("/users").catch((e) => {
|
53
|
-
expect(e.message).toMatch("Unexpected token")
|
54
|
-
})
|
55
|
-
})
|
56
|
-
|
57
|
-
it("network errors get rejected", async () => {
|
58
|
-
xhrMock.get("http://localhost/users", () => {
|
59
|
-
return Promise.reject(new Error())
|
60
|
-
})
|
61
|
-
expect.assertions(1)
|
62
|
-
await get("/users").catch((e) => {
|
63
|
-
expect(e.message).toEqual("An error occurred during the transaction")
|
64
|
-
})
|
65
|
-
})
|
66
|
-
|
67
|
-
it("server errors get rejected", async () => {
|
68
|
-
xhrMock.get("http://localhost/users", (_req, res) => {
|
69
|
-
return res.status(401).body('{"error":"Unauthorized"}')
|
70
|
-
})
|
71
|
-
expect.assertions(1)
|
72
|
-
await get("/users").catch((e) => {
|
73
|
-
expect(e.error).toEqual("Unauthorized")
|
74
|
-
})
|
75
|
-
})
|
76
|
-
|
77
|
-
it("server errors parsing errors get rejected", async () => {
|
78
|
-
xhrMock.get("http://localhost/users", (_req, res) => {
|
79
|
-
return res.status(401).body("Unauthorized")
|
80
|
-
})
|
81
|
-
expect.assertions(1)
|
82
|
-
await get("/users").catch((e) => {
|
83
|
-
expect(e.message).toMatch("Unexpected token")
|
84
|
-
})
|
85
|
-
})
|
86
|
-
|
87
|
-
it("params get attached as query string", async () => {
|
88
|
-
xhrMock.get("http://localhost/users?name=foo", (_req, res) => {
|
89
|
-
return res.status(200).body(`{"name":"foo"}`)
|
90
|
-
})
|
91
|
-
const { data } = await get("/users", { name: "foo" })
|
92
|
-
expect(data.name).toEqual("foo")
|
93
|
-
})
|
94
|
-
})
|
95
|
-
|
96
|
-
describe("patch", () => {
|
97
|
-
it("sends X-CSRF-TOKEN header", async () => {
|
98
|
-
xhrMock.patch("http://localhost/users", (req, res) => {
|
99
|
-
expect(req.header("X-CSRF-TOKEN")).toEqual(token)
|
100
|
-
return res.status(200).body('{"message":"Ok"}')
|
101
|
-
})
|
102
|
-
await patch("/users")
|
103
|
-
})
|
104
|
-
|
105
|
-
it("sends Content-Type header", async () => {
|
106
|
-
xhrMock.patch("http://localhost/users", (req, res) => {
|
107
|
-
expect(req.header("Content-Type")).toEqual(
|
108
|
-
"application/json; charset=utf-8"
|
109
|
-
)
|
110
|
-
return res.status(200).body('{"message":"Ok"}')
|
111
|
-
})
|
112
|
-
await patch("/users")
|
113
|
-
})
|
114
|
-
|
115
|
-
it("sends Accept header", async () => {
|
116
|
-
xhrMock.patch("http://localhost/users", (req, res) => {
|
117
|
-
expect(req.header("Accept")).toEqual("application/json")
|
118
|
-
return res.status(200).body('{"message":"Ok"}')
|
119
|
-
})
|
120
|
-
await patch("/users")
|
121
|
-
})
|
122
|
-
|
123
|
-
it("sends JSON data", async () => {
|
124
|
-
xhrMock.patch("http://localhost/users", (req, res) => {
|
125
|
-
expect(req.body()).toEqual('{"email":"mail@example.com"}')
|
126
|
-
return res.status(200).body('{"message":"Ok"}')
|
127
|
-
})
|
128
|
-
await patch("/users", { email: "mail@example.com" })
|
129
|
-
})
|
130
|
-
})
|
131
|
-
|
132
|
-
describe("post", () => {
|
133
|
-
it("sends X-CSRF-TOKEN header", async () => {
|
134
|
-
xhrMock.post("http://localhost/users", (req, res) => {
|
135
|
-
expect(req.header("X-CSRF-TOKEN")).toEqual(token)
|
136
|
-
return res.status(200).body('{"message":"Ok"}')
|
137
|
-
})
|
138
|
-
await post("/users")
|
139
|
-
})
|
140
|
-
|
141
|
-
it("sends Content-Type header", async () => {
|
142
|
-
xhrMock.post("http://localhost/users", (req, res) => {
|
143
|
-
expect(req.header("Content-Type")).toEqual(
|
144
|
-
"application/json; charset=utf-8"
|
145
|
-
)
|
146
|
-
return res.status(200).body('{"message":"Ok"}')
|
147
|
-
})
|
148
|
-
await post("/users")
|
149
|
-
})
|
150
|
-
|
151
|
-
it("sends Accept header", async () => {
|
152
|
-
xhrMock.post("http://localhost/users", (req, res) => {
|
153
|
-
expect(req.header("Accept")).toEqual("application/json")
|
154
|
-
return res.status(200).body('{"message":"Ok"}')
|
155
|
-
})
|
156
|
-
await post("/users")
|
157
|
-
})
|
158
|
-
|
159
|
-
it("sends JSON data", async () => {
|
160
|
-
xhrMock.post("http://localhost/users", (req, res) => {
|
161
|
-
expect(req.body()).toEqual('{"email":"mail@example.com"}')
|
162
|
-
return res.status(200).body('{"message":"Ok"}')
|
163
|
-
})
|
164
|
-
await post("/users", { email: "mail@example.com" })
|
165
|
-
})
|
166
|
-
})
|
167
|
-
|
168
|
-
afterEach(() => xhrMock.teardown())
|
@@ -1,38 +0,0 @@
|
|
1
|
-
import { on } from "../events"
|
2
|
-
|
3
|
-
describe("on", () => {
|
4
|
-
const callback = jest.fn()
|
5
|
-
|
6
|
-
beforeEach(() => {
|
7
|
-
document.body.innerHTML = `
|
8
|
-
<ul class="list">
|
9
|
-
<li class="first item"><span>One</span></li>
|
10
|
-
<li class="second item">Two</li>
|
11
|
-
</ul>
|
12
|
-
`
|
13
|
-
})
|
14
|
-
|
15
|
-
it("adds event listener to base node", () => {
|
16
|
-
const baseNode = document.querySelector(".list")
|
17
|
-
const spy = jest.spyOn(baseNode, "addEventListener")
|
18
|
-
on("click", ".list", ".item", callback)
|
19
|
-
expect(spy).toHaveBeenCalledWith("click", expect.any(Function))
|
20
|
-
spy.mockReset()
|
21
|
-
})
|
22
|
-
|
23
|
-
it("event triggered on matching child node calls callback", () => {
|
24
|
-
const childNode = document.querySelector(".first.item")
|
25
|
-
on("click", ".list", ".item", callback)
|
26
|
-
childNode.click()
|
27
|
-
expect(callback).toHaveBeenCalledWith(expect.any(MouseEvent))
|
28
|
-
})
|
29
|
-
|
30
|
-
it("event triggered on child of registered target still calls callback", () => {
|
31
|
-
const child = document.querySelector(".first.item span")
|
32
|
-
on("click", ".list", ".item", callback)
|
33
|
-
child.click()
|
34
|
-
expect(callback).toHaveBeenCalledWith(expect.any(MouseEvent))
|
35
|
-
})
|
36
|
-
|
37
|
-
afterEach(() => callback.mockReset())
|
38
|
-
})
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|