@robotical/martyblocksjr 4.2.1 → 4.2.2

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.
@@ -390,6 +390,11 @@ div.frame {
390
390
  outline-offset: 4px;
391
391
  }
392
392
 
393
+ #blockspalette .categoryselector button[aria-pressed="true"]:focus,
394
+ #blockspalette .categoryselectorright button[aria-pressed="true"]:focus{
395
+ outline: none;
396
+ }
397
+
393
398
  #blockspalette .categoryselectorright{
394
399
  display: inline-block;
395
400
  word-spacing: -1;
@@ -313,11 +313,11 @@
313
313
  }
314
314
 
315
315
  .marty-mode-card {
316
- background: url('../assets/ui/viewOn.png') no-repeat left top;
317
- background-size: 100%;
316
+ background: url('../assets/ui/viewOnCompactWideLabel.png') no-repeat left top;
317
+ background-size: 100% 100%;
318
318
  position: relative;
319
319
  display: inline-block;
320
- width: ${css_vh(29.95)};
320
+ width: ${css_vh(23.18)};
321
321
  height: ${css_vh(10.16)};
322
322
  margin: 0px;
323
323
  margin-bottom: ${css_vh(-0.39)};
@@ -346,7 +346,7 @@
346
346
  position: absolute;
347
347
  text-align: center;
348
348
  top: ${css_vh(3.91)};
349
- left: ${css_vh(8.46)};
349
+ left: ${css_vh(9.24)};
350
350
  margin: 0px;
351
351
  padding: 0px;
352
352
  line-height: ${css_vh(2.60)};
@@ -356,7 +356,7 @@
356
356
  font-family: 'Lato Regular';
357
357
  font-weight: bold;
358
358
  font-size: ${css_vh(1.69)};
359
- width: ${css_vh(13.54)};
359
+ width: ${css_vh(11.97)};
360
360
  cursor: default;
361
361
  color: #F9A737;
362
362
  }
@@ -493,9 +493,9 @@
493
493
  position: absolute;
494
494
  background: url('../assets/paint/paintbrush.svg');
495
495
  background-size: 100% 100%;
496
- width: ${css_vh(5.73)};
497
- height: ${css_vh(5.73)};
498
- top: ${css_vh(2.21)};
496
+ width: ${css_vh(5.08)};
497
+ height: ${css_vh(5.08)};
498
+ top: ${css_vh(2.54)};
499
499
  left: ${css_vh(17.45)};
500
500
  margin: 0px;
501
501
  padding: 0px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robotical/martyblocksjr",
3
- "version": "4.2.1",
3
+ "version": "4.2.2",
4
4
  "description": "ScratchJr",
5
5
  "repository": {
6
6
  "type": "git",
@@ -378,6 +378,7 @@ describe('Accessibility shell audit', () => {
378
378
  const motionButton = document.getElementById('sprite-motion');
379
379
  return motionButton && motionButton.getAttribute('aria-pressed') === 'true';
380
380
  }, { timeout: 5_000 });
381
+ expect((await getFocusStyles(page, '#sprite-motion')).outlineStyle).toBe('none');
381
382
  await page.waitForSelector('#forward_block[role="button"]', { timeout: 30_000 });
382
383
 
383
384
  await expectNamedControls(page, ['#forward_block', '#back_block']);
@@ -72,7 +72,94 @@ async function openEditor() {
72
72
  return { browser, page, errors };
73
73
  }
74
74
 
75
- describe("animated sprite paint editing", () => {
75
+ async function dragBlockToScripts(page, categorySelector, blockSelector, blockType) {
76
+ const blockCount = await page.evaluate(() => window.ScratchJr.getBlocks().length);
77
+ await page.click(categorySelector);
78
+ await page.waitForSelector(blockSelector, { visible: true });
79
+
80
+ const source = await page.$eval(blockSelector, (node) => {
81
+ const rect = node.getBoundingClientRect();
82
+ return {
83
+ x: rect.left + rect.width / 2,
84
+ y: rect.top + rect.height / 2,
85
+ };
86
+ });
87
+ const target = await page.$eval("#scripts", (node) => {
88
+ const rect = node.getBoundingClientRect();
89
+ return {
90
+ x: rect.left + Math.min(220, rect.width / 2),
91
+ y: rect.top + Math.min(170, rect.height / 2),
92
+ };
93
+ });
94
+
95
+ await page.mouse.move(source.x, source.y);
96
+ await page.mouse.down();
97
+ await page.mouse.move(target.x, target.y, { steps: 12 });
98
+ await page.mouse.up();
99
+
100
+ await page.waitForFunction(
101
+ (before, type) => window.ScratchJr.getBlocks().length > before
102
+ && window.ScratchJr.getBlocks().some((block) => block.blocktype === type),
103
+ { timeout: 30_000 },
104
+ blockCount,
105
+ blockType
106
+ );
107
+ }
108
+
109
+ async function getSelectedSpritePaintState(page) {
110
+ return page.evaluate(() => {
111
+ const sprite = window.ScratchJr && window.ScratchJr.getSprite();
112
+ const thumb = sprite && sprite.thumbnail;
113
+ const brush = thumb && thumb.querySelector(".brush");
114
+ if (!sprite || !thumb || !brush) {
115
+ throw new Error("Selected sprite paint controls were not found");
116
+ }
117
+ return {
118
+ md5: sprite.md5,
119
+ thumbClass: thumb.className,
120
+ brushDisplay: window.getComputedStyle(brush).display,
121
+ blockTypes: window.ScratchJr.getBlocks().map((block) => block.blocktype),
122
+ };
123
+ });
124
+ }
125
+
126
+ describe("sprite paint editing availability", () => {
127
+ it(
128
+ "keeps Marty paint editing disabled after dropping a block",
129
+ async () => {
130
+ const { browser, page, errors } = await openEditor();
131
+
132
+ try {
133
+ const beforeDrop = await getSelectedSpritePaintState(page);
134
+ expect(beforeDrop.md5).toBe("Sprites_Marty.svg");
135
+ expect(beforeDrop.thumbClass).toContain("martynoneditable");
136
+ expect(beforeDrop.brushDisplay).toBe("none");
137
+
138
+ await dragBlockToScripts(page, "#sprite-motion", "#forward_block", "forward");
139
+
140
+ const afterDrop = await getSelectedSpritePaintState(page);
141
+ expect(afterDrop.thumbClass).toContain("martynoneditable");
142
+ expect(afterDrop.brushDisplay).toBe("none");
143
+ expect(afterDrop.blockTypes).toContain("forward");
144
+
145
+ const paintFrameVisible = await page.evaluate(() => {
146
+ const brush = window.ScratchJr.getSprite().thumbnail.querySelector(".brush");
147
+ brush.dispatchEvent(new PointerEvent("pointerdown", {
148
+ bubbles: true,
149
+ cancelable: true,
150
+ pointerType: "mouse",
151
+ }));
152
+ return window.getComputedStyle(document.getElementById("paintframe")).display !== "none";
153
+ });
154
+ expect(paintFrameVisible).toBe(false);
155
+ expect(errors).toEqual([]);
156
+ } finally {
157
+ await browser.close();
158
+ }
159
+ },
160
+ 60_000
161
+ );
162
+
76
163
  it(
77
164
  "disables paint editing for the animated bee in the library and sprite panel",
78
165
  async () => {
@@ -231,7 +318,8 @@ describe("animated sprite paint editing", () => {
231
318
  expect(layoutState.selectedBackgroundSize).toBe("100% 100%");
232
319
  expect(layoutState.name.right).toBeLessThanOrEqual(layoutState.brush.left + 0.5);
233
320
  expect(layoutState.brush.left).toBeGreaterThanOrEqual(layoutState.selected.left);
234
- expect(layoutState.brush.right).toBeLessThanOrEqual(layoutState.selected.right + 0.5);
321
+ expect(layoutState.selected.right - layoutState.brush.right)
322
+ .toBeGreaterThanOrEqual(layoutState.brush.width * 0.1);
235
323
  expect(layoutState.brush.top).toBeGreaterThanOrEqual(layoutState.selected.top);
236
324
  expect(layoutState.brush.bottom).toBeLessThanOrEqual(layoutState.selected.bottom);
237
325
 
@@ -249,6 +249,77 @@ describe("Marty script activation paths", () => {
249
249
  }
250
250
  });
251
251
 
252
+ it("keeps the Marty mode sidebar card and full label stable after block drops", async () => {
253
+ const { browser, page, errors } = await openPage("/editor.html?mode=edit");
254
+ try {
255
+ await waitForEditorReady(page);
256
+ const spriteCardLayout = await page.evaluate(() => {
257
+ const card = document.querySelector("#spritecc .spritethumb[aria-pressed=\"true\"]");
258
+ const label = card && card.querySelector(".sname");
259
+ if (!card || !label) {
260
+ throw new Error("Selected sprite card layout was not found");
261
+ }
262
+ return {
263
+ cardWidth: card.getBoundingClientRect().width,
264
+ labelWidth: label.getBoundingClientRect().width
265
+ };
266
+ });
267
+
268
+ await setMartyMode(page, true);
269
+ const getMartyCardLayout = () => page.evaluate(() => {
270
+ const card = document.getElementById("martyModeSidebarCard");
271
+ const label = card && card.querySelector(".marty-mode-card-label");
272
+ if (!card || !label) {
273
+ throw new Error("Marty mode sidebar card layout was not found");
274
+ }
275
+ const cardStyle = window.getComputedStyle(card);
276
+ const labelStyle = window.getComputedStyle(label);
277
+ const cardRect = card.getBoundingClientRect();
278
+ const labelRect = label.getBoundingClientRect();
279
+ return {
280
+ className: card.className,
281
+ cardWidth: cardRect.width,
282
+ cardLeft: cardRect.left,
283
+ cardRight: cardRect.right,
284
+ labelText: label.textContent,
285
+ labelWidth: labelRect.width,
286
+ labelLeft: labelRect.left,
287
+ labelRight: labelRect.right,
288
+ labelClientWidth: label.clientWidth,
289
+ labelScrollWidth: label.scrollWidth,
290
+ hasBrush: Boolean(card.querySelector(".brush")),
291
+ backgroundImage: cardStyle.backgroundImage,
292
+ backgroundSize: cardStyle.backgroundSize,
293
+ overflow: labelStyle.overflow,
294
+ textOverflow: labelStyle.textOverflow,
295
+ whiteSpace: labelStyle.whiteSpace
296
+ };
297
+ });
298
+ const martyCardLayout = await getMartyCardLayout();
299
+
300
+ expect(martyCardLayout.cardWidth).toBeCloseTo(spriteCardLayout.cardWidth, 1);
301
+ expect(martyCardLayout.labelWidth).toBeGreaterThan(spriteCardLayout.labelWidth);
302
+ expect(martyCardLayout.labelLeft).toBeGreaterThanOrEqual(martyCardLayout.cardLeft);
303
+ expect(martyCardLayout.labelRight).toBeLessThanOrEqual(martyCardLayout.cardRight);
304
+ expect(martyCardLayout.labelText).toBe("Marty Mode");
305
+ expect(martyCardLayout.hasBrush).toBe(false);
306
+ expect(martyCardLayout.backgroundImage).toContain("viewOnCompactWideLabel.png");
307
+ expect(martyCardLayout.backgroundSize).toBe("100% 100%");
308
+ expect(martyCardLayout).toMatchObject({
309
+ overflow: "hidden",
310
+ textOverflow: "ellipsis",
311
+ whiteSpace: "nowrap"
312
+ });
313
+ expect(martyCardLayout.labelScrollWidth).toBeLessThanOrEqual(martyCardLayout.labelClientWidth);
314
+
315
+ await dragMartyBlock(page);
316
+ expect(await getMartyCardLayout()).toEqual(martyCardLayout);
317
+ expect(errors).toEqual([]);
318
+ } finally {
319
+ await browser.close();
320
+ }
321
+ }, 60000);
322
+
252
323
  it("activates the script after duplicating a page in Marty mode", async () => {
253
324
  const { browser, page, errors } = await openPage("/editor.html?mode=edit");
254
325
  try {