@robotical/martyblocksjr 4.2.2 → 4.2.4

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.
Files changed (47) hide show
  1. package/editions/free/src/app.bundle.js +1 -1
  2. package/editions/free/src/css/editor.css +5 -0
  3. package/editions/free/src/css/editorleftpanel.css +12 -6
  4. package/editions/free/src/inapp/about.html +55 -26
  5. package/editions/free/src/inapp/blocks.html +16 -459
  6. package/editions/free/src/inapp/images/interface.png +0 -0
  7. package/editions/free/src/inapp/images/paint.png +0 -0
  8. package/editions/free/src/inapp/interface.html +136 -123
  9. package/editions/free/src/inapp/style/about.css +333 -21
  10. package/editions/free/src/inapp/style/blocks.css +423 -82
  11. package/editions/free/src/inapp/style/interface.css +178 -453
  12. package/editions/free/src/localizations/bg.json +36 -2
  13. package/editions/free/src/localizations/ca.json +36 -2
  14. package/editions/free/src/localizations/cs.json +36 -2
  15. package/editions/free/src/localizations/cy.json +36 -2
  16. package/editions/free/src/localizations/da.json +36 -2
  17. package/editions/free/src/localizations/de.json +36 -2
  18. package/editions/free/src/localizations/el.json +36 -2
  19. package/editions/free/src/localizations/en.json +114 -7
  20. package/editions/free/src/localizations/es.json +36 -2
  21. package/editions/free/src/localizations/fi.json +36 -2
  22. package/editions/free/src/localizations/fr.json +36 -2
  23. package/editions/free/src/localizations/it.json +36 -2
  24. package/editions/free/src/localizations/ja.json +36 -2
  25. package/editions/free/src/localizations/ko.json +36 -2
  26. package/editions/free/src/localizations/nl.json +36 -2
  27. package/editions/free/src/localizations/no.json +36 -2
  28. package/editions/free/src/localizations/pl.json +36 -2
  29. package/editions/free/src/localizations/pt-br.json +36 -2
  30. package/editions/free/src/localizations/pt.json +36 -2
  31. package/editions/free/src/localizations/sv.json +36 -2
  32. package/editions/free/src/localizations/th.json +36 -2
  33. package/editions/free/src/localizations/tr.json +36 -2
  34. package/editions/free/src/localizations/uk.json +36 -2
  35. package/editions/free/src/localizations/zh-cn.json +36 -2
  36. package/editions/free/src/localizations/zh-tw.json +36 -2
  37. package/package.json +1 -1
  38. package/scripts/a11y-structure.mjs +9 -2
  39. package/tests/BlockGuideRegistry.test.js +60 -0
  40. package/tests/MartyManager.test.js +88 -0
  41. package/tests/e2e/accessibility.e2e.test.js +153 -10
  42. package/tests/e2e/blocks-jr-hidden-blocks.e2e.test.js +84 -0
  43. package/tests/e2e/chromium-79-smoke.test.js +12 -17
  44. package/tests/e2e/marty-connection-ui.e2e.test.js +177 -12
  45. package/tests/e2e/microbit-extension-project-reload.e2e.test.js +1 -6
  46. package/tests/e2e/project-load-progress-loop.e2e.test.js +1 -6
  47. package/tests/e2e/sidebar-scrollbars.e2e.test.js +179 -0
@@ -0,0 +1,179 @@
1
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
2
+ import puppeteer from 'puppeteer';
3
+ import { spawn } from 'child_process';
4
+ import http from 'http';
5
+
6
+ const PORT = 3022;
7
+ const HOST = `http://localhost:${PORT}`;
8
+
9
+ let server;
10
+
11
+ async function waitForServer(maxAttempts = 20) {
12
+ for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
13
+ const ok = await new Promise((resolve) => {
14
+ const req = http.get(`${HOST}/`, (res) => {
15
+ res.destroy();
16
+ resolve(true);
17
+ });
18
+ req.on('error', () => resolve(false));
19
+ });
20
+ if (ok) {
21
+ return;
22
+ }
23
+ await new Promise((resolve) => setTimeout(resolve, 500));
24
+ }
25
+ throw new Error('Local server did not start in time');
26
+ }
27
+
28
+ beforeAll(async () => {
29
+ server = spawn('python3', ['-m', 'http.server', `${PORT}`, '--directory', 'editions/free/src'], {
30
+ stdio: 'ignore'
31
+ });
32
+ await waitForServer();
33
+ }, 30_000);
34
+
35
+ afterAll(() => {
36
+ if (server) {
37
+ server.kill();
38
+ }
39
+ });
40
+
41
+ async function openEditor() {
42
+ const browser = await puppeteer.launch({
43
+ headless: true,
44
+ args: ['--no-sandbox']
45
+ });
46
+ const page = await browser.newPage();
47
+ const errors = [];
48
+
49
+ page.on('pageerror', (error) => errors.push(error.message || String(error)));
50
+ page.on('console', (message) => {
51
+ if (message.type() === 'error') {
52
+ errors.push(message.text());
53
+ }
54
+ });
55
+ await page.goto(`${HOST}/editor.html?mode=edit`, {
56
+ waitUntil: 'networkidle2',
57
+ timeout: 30_000
58
+ });
59
+ await page.waitForFunction(() => {
60
+ const backdrop = document.getElementById('backdrop');
61
+ return Boolean(
62
+ window.ScratchJr &&
63
+ window.ScratchJr.stage &&
64
+ document.getElementById('spritecc') &&
65
+ document.getElementById('pagecc') &&
66
+ document.getElementById('scrollbar') &&
67
+ document.getElementById('pagescrollbar') &&
68
+ backdrop &&
69
+ window.getComputedStyle(backdrop).display === 'none'
70
+ );
71
+ }, { timeout: 30_000 });
72
+ return { browser, page, errors };
73
+ }
74
+
75
+ describe('editor sidebar scrollbars', () => {
76
+ it('shows and synchronizes persistent scrollbars when sprites and pages overflow', async () => {
77
+ const { browser, page, errors } = await openEditor();
78
+
79
+ try {
80
+ const naturalSpriteState = await page.evaluate(() => {
81
+ const spriteContainer = document.getElementById('spriteScrollContainer');
82
+ const addSprite = document.getElementById('addsprite');
83
+ return {
84
+ addButtonScrollsWithPanel: addSprite.parentNode === spriteContainer,
85
+ overflow: spriteContainer.scrollHeight - spriteContainer.clientHeight,
86
+ scrollbarVisible: document.getElementById('scrollbar').classList.contains('on')
87
+ };
88
+ });
89
+ expect(naturalSpriteState.addButtonScrollsWithPanel).toBe(true);
90
+ if (naturalSpriteState.overflow <= 1) {
91
+ expect(naturalSpriteState.scrollbarVisible).toBe(false);
92
+ }
93
+
94
+ await page.evaluate(() => {
95
+ const spriteSpacer = document.createElement('div');
96
+ spriteSpacer.id = 'sprite-scroll-test-spacer';
97
+ spriteSpacer.style.height = '800px';
98
+ document.getElementById('spritecc').appendChild(spriteSpacer);
99
+
100
+ const pageSpacer = document.createElement('div');
101
+ pageSpacer.id = 'page-scroll-test-spacer';
102
+ pageSpacer.style.height = '800px';
103
+ document.getElementById('pagelist').appendChild(pageSpacer);
104
+ });
105
+
106
+ await page.waitForFunction(() =>
107
+ document.getElementById('scrollbar').classList.contains('on') &&
108
+ document.getElementById('pagescrollbar').classList.contains('on')
109
+ );
110
+
111
+ const initialState = await page.evaluate(() => ({
112
+ spriteRole: document.getElementById('scrollbar').getAttribute('role'),
113
+ spriteLabel: document.getElementById('scrollbar').getAttribute('aria-label'),
114
+ spriteControls: document.getElementById('scrollbar').getAttribute('aria-controls'),
115
+ pageRole: document.getElementById('pagescrollbar').getAttribute('role'),
116
+ pageLabel: document.getElementById('pagescrollbar').getAttribute('aria-label'),
117
+ pageControls: document.getElementById('pagescrollbar').getAttribute('aria-controls'),
118
+ spriteThumbHeight: document.getElementById('sbthumb').offsetHeight,
119
+ pageThumbHeight: document.getElementById('pagesbthumb').offsetHeight,
120
+ addSpriteTop: document.getElementById('addsprite').getBoundingClientRect().top
121
+ }));
122
+ expect(initialState).toEqual({
123
+ spriteRole: 'scrollbar',
124
+ spriteLabel: 'Characters',
125
+ spriteControls: 'spriteScrollContainer',
126
+ pageRole: 'scrollbar',
127
+ pageLabel: 'Pages',
128
+ pageControls: 'pagecc',
129
+ spriteThumbHeight: expect.any(Number),
130
+ pageThumbHeight: expect.any(Number),
131
+ addSpriteTop: expect.any(Number)
132
+ });
133
+ expect(initialState.spriteThumbHeight).toBeGreaterThan(0);
134
+ expect(initialState.pageThumbHeight).toBeGreaterThan(0);
135
+
136
+ await page.evaluate(() => {
137
+ const spriteContainer = document.querySelector('#library .spritethumbs');
138
+ const pageContainer = document.getElementById('pagecc');
139
+ spriteContainer.scrollTop = spriteContainer.scrollHeight;
140
+ pageContainer.scrollTop = pageContainer.scrollHeight;
141
+ });
142
+ await page.waitForFunction(() =>
143
+ Number(document.getElementById('scrollbar').getAttribute('aria-valuenow')) > 0 &&
144
+ Number(document.getElementById('pagescrollbar').getAttribute('aria-valuenow')) > 0
145
+ );
146
+
147
+ const scrolledState = await page.evaluate(() => ({
148
+ spriteThumbTop: document.getElementById('sbthumb').offsetTop,
149
+ pageThumbTop: document.getElementById('pagesbthumb').offsetTop,
150
+ spriteValue: Number(document.getElementById('scrollbar').getAttribute('aria-valuenow')),
151
+ pageValue: Number(document.getElementById('pagescrollbar').getAttribute('aria-valuenow')),
152
+ addSpriteTop: document.getElementById('addsprite').getBoundingClientRect().top
153
+ }));
154
+ expect(scrolledState.spriteThumbTop).toBeGreaterThan(0);
155
+ expect(scrolledState.pageThumbTop).toBeGreaterThan(0);
156
+ expect(scrolledState.spriteValue).toBeGreaterThan(0);
157
+ expect(scrolledState.pageValue).toBeGreaterThan(0);
158
+ expect(scrolledState.addSpriteTop).toBeLessThan(initialState.addSpriteTop);
159
+
160
+ await page.evaluate(() => {
161
+ document.getElementById('pagecc').scrollTop = 0;
162
+ });
163
+ const pageScrollBar = await page.$('#pagescrollbar');
164
+ const pageScrollBarBox = await pageScrollBar.boundingBox();
165
+ await page.mouse.click(
166
+ pageScrollBarBox.x + (pageScrollBarBox.width / 2),
167
+ pageScrollBarBox.y + pageScrollBarBox.height - 2
168
+ );
169
+ await page.waitForFunction(() => document.getElementById('pagecc').scrollTop > 0);
170
+
171
+ await page.focus('#pagescrollbar');
172
+ await page.keyboard.press('Home');
173
+ await page.waitForFunction(() => document.getElementById('pagecc').scrollTop === 0);
174
+ expect(errors).toEqual([]);
175
+ } finally {
176
+ await browser.close();
177
+ }
178
+ }, 45_000);
179
+ });