<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>EC-CUBE &#8211; ねこねこネットワーク</title>
	<atom:link href="https://neko-neko.sai-net.work/category/ec-cube/feed/" rel="self" type="application/rss+xml" />
	<link>https://neko-neko.sai-net.work</link>
	<description></description>
	<lastBuildDate>Thu, 03 Oct 2024 12:21:11 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>
	<item>
		<title>【ECCUBE】【playwrite】店舗設定：個別設定のE2Eテストコード全体構成</title>
		<link>https://neko-neko.sai-net.work/759/</link>
					<comments>https://neko-neko.sai-net.work/759/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Thu, 03 Oct 2024 12:11:38 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<category><![CDATA[テスト]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=759</guid>

					<description><![CDATA[2024-10-03筆者が苦戦したE2E [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>2024-10-03<br>筆者が苦戦したE2Eテストコードを記録として残す。<br>特に、fixtureを使ったDBへのレコード作成！！ファイル同士の関連性が分からな過ぎた (´;ω;｀)</p>



<h2 class="wp-block-heading">前提条件</h2>



<ul class="wp-block-list">
<li>ECCUBE がローカルに保存されている事</li>
</ul>



<p></p>



<h2 class="wp-block-heading">コード全体</h2>



<h4 class="wp-block-heading">(1) 【spec】E2Eテストコード</h4>



<p>《場所》<br>e2e-tests/spec/admin/tenant/individual_settings.spec.ts</p>



<p>《test関数説明》<br>個別設定：個別設定ページで値を入力し保存・反映がされるか確認<br>定休日カレンダー設定_新規作成：定休日が新規作成できるかどうか確認<br>定休日カレンダー設定_複数行_ページ遷移確認：定休日レコードが複数ある場合のページネーション確認</p>



<pre class="wp-block-code"><code>import {test} from "../../../fixtures/admin_login.fixture";
import {AdminShopIndividualSettingsPage} from "../../../pages/admin/tenant/individual_settings.page";

test('個別設定',
    {tag: &#91;"@tenant_owner_a"]},
    async ({loginPage,page}) =&gt; { 
        const ShopIndividualSettingsPage = new AdminShopIndividualSettingsPage(page);

        // ログイン確認
        await loginPage.seeAfterLoginSuccess();

        // 店舗設定を開く
        await ShopIndividualSettingsPage.gotoIndividualSetting();

        // タブタイトルの存在確認
        await ShopIndividualSettingsPage.seeTabTitle();

        // 値入力
        await ShopIndividualSettingsPage.fillIndividualSetting(
            {
                businessHours: 'サンプル営業時間',
                postage: '123456789',
                taxSet: '999999999'
            }
        );
        // 保存
        await ShopIndividualSettingsPage.clickRegisterButton();

        // 反映確認
        await ShopIndividualSettingsPage.seeInputIndividualSetting();

        // 値入力
        await ShopIndividualSettingsPage.fillIndividualSetting(
            {
                businessHours: '',
                postage: '',
                taxSet: ''
            }
        );
        // 保存
        await ShopIndividualSettingsPage.clickRegisterButton();

        // 反映確認
        await ShopIndividualSettingsPage.seeDeleteIndividualSetting();
        await ShopIndividualSettingsPage.seeSavedMessage();
    }
);

test('定休日カレンダー設定_新規作成',
    {tag: &#91;"@tenant_owner_a"]},
    async ({loginPage,page}) =&gt; {
        const ShopIndividualSettingsPage = new AdminShopIndividualSettingsPage(page);

        // ログイン確認
        await loginPage.seeAfterLoginSuccess();

        // 店舗設定を開く
        await ShopIndividualSettingsPage.gotoIndividualSetting();

        // 値入力
        await ShopIndividualSettingsPage.fillCalendarHoliday(
            {
                calendarTitle: '定休日はありません_新規作成',
                calendarHoliday: '2024-10-07'
            }
        );
        // 保存
        await ShopIndividualSettingsPage.clickCreateButton();
        await ShopIndividualSettingsPage.clickRegisterButton();

        // 反映確認
        await ShopIndividualSettingsPage.seeInputHolidayCalendar();
    }
);

test('定休日カレンダー設定_複数行_ページ遷移確認',
    {tag: &#91;"@tenant_owner_a"]},
    async ({loginPage,page}) =&gt; {
        const ShopIndividualSettingsPage = new AdminShopIndividualSettingsPage(page);

        // ログイン確認
        await loginPage.seeAfterLoginSuccess();

        // 店舗設定を開く
        await ShopIndividualSettingsPage.gotoIndividualSetting();

        // 11行のカレンダー作成
        await ShopIndividualSettingsPage.createCalendar(10);

        // 次へボタン押下
        await ShopIndividualSettingsPage.clickNextPageButton();

        // 画面遷移されているか確認
        await ShopIndividualSettingsPage.seePrevPageButton();
    }
);</code></pre>



<p></p>



<h4 class="wp-block-heading">(2) 【page】(1)で使うクラス・関数まとめ</h4>



<p>《場所》<br>e2e-tests/pages/admin/tenant/individual_settings.page.ts</p>



<pre class="wp-block-code"><code>import {expect, Locator, Page} from "@playwright/test";
import {ECCUBE_ADMIN_ROUTE} from "../../../config/default.config";
import {createCalendar} from "../../../fixtures/admin/tenant/individual_settings.fixture";

export class AdminShopIndividualSettingsPage {
    readonly page: Page;
    readonly url: string;
    readonly businessHours: Locator;        // 店舗情報
    readonly postage: Locator;              // 送料
    readonly taxSet: Locator;               // 税設定
    readonly registerButton: Locator;       // 登録
    readonly createButton: Locator;         // 新規作成
    readonly calendarTitle: Locator;        // 入力：カレンダータイトル
    readonly calendarHoliday: Locator;      // 入力：定休日
    readonly confCalenderTitle: Locator;    // 確認：カレンダータイトル
    readonly calenderRow01: Locator;        // 登録カレンダー1行目
    readonly nextPage: Locator;             // 次へ
    readonly prevPage: Locator;             // 前へ

    constructor(page: Page) {
        this.page = page;
        this.url = `${ECCUBE_ADMIN_ROUTE}/tenant/tradelaw`;
        this.businessHours = page.locator('#shop_master_business_hour');
        this.postage = page.locator('#shop_master_delivery_free_amount');
        this.taxSet = page.locator('#shop_master_invoice_registration_number');
        this.calendarTitle = page.locator('#calendar_item_new #calendar_title');
        this.calendarHoliday = page.locator('#calendar_item_new #calendar_holiday');
        this.nextPage = page.locator('.pagination .page-item:has-text("次へ")');
        this.prevPage = page.locator('.pagination .page-item:has-text("前へ")');
        this.registerButton = page.getByRole('button', {name: '登録'});
        this.createButton = page.getByRole('button', {name: '新規作成'});
        this.calenderRow01 = page.locator('.card-body .table tbody tr').nth(1);
    }

    // 対象URLへ遷移
    async goto() {
        await this.page.goto(this.url);
    }

    // メニュー操作
    async gotoIndividualSetting() {
        await this.page.getByRole('link', {name: '店舗設定'}).click();
        await this.page.getByRole('link', {name: '個別設定'}).click();
    }

    // タブタイトルの存在確認
    async seeTabTitle() {
        await expect(this.page).toHaveTitle('店舗設定 個別設定 - EC-CUBE SHOP_tenant_1');
    }

    // 値入力：
    // 定休日以外の設定
    async fillIndividualSetting(individualSetting: {
            businessHours: string,
            postage: string,
            taxSet: string,
    }){
        await this.businessHours.fill(individualSetting.businessHours);
        await this.postage.fill(individualSetting.postage);
        await this.taxSet.fill(individualSetting.taxSet);
    }
    // 定休日設定
    async fillCalendarHoliday(calendarHolidaySetting: {
        calendarTitle: string,
        calendarHoliday: string,
    }){
        await this.calendarTitle.fill(calendarHolidaySetting.calendarTitle);
        await this.calendarHoliday.fill(calendarHolidaySetting.calendarHoliday);
    }

    //　反映確認：
    // 入力判定
    async seeInputIndividualSetting() {
        await expect(this.businessHours).toHaveValue('サンプル営業時間');
        await expect(this.postage).toHaveValue('123,456,789');
        await expect(this.taxSet).toHaveValue('999999999');
    }
    async seeInputHolidayCalendar() {
        await expect(this.calenderRow01).toContainText('定休日はありません_新規作成');
        await expect(this.calenderRow01).toContainText('2024/10/07');
    }

    // 削除判定
    async seeDeleteIndividualSetting() {
        await expect(this.businessHours).toHaveValue('');
        await expect(this.postage).toHaveValue('');
        await expect(this.taxSet).toHaveValue('');
    }
    // async seeDeleteHolidayCalendar() {
    //     await expect(this.businessHours).toHaveValue('');
    //     await expect(this.postage).toHaveValue('');
    // }

    // 登録ボタン押下
    async clickRegisterButton() {
        await this.registerButton.click();
    }

    // 新規作成ボタン押下
    async clickCreateButton() {
        await this.createButton.click();
    }

    // 登録ボタンの表示確認
    async seeRegisterButton() {
        await expect(this.registerButton).toBeVisible();
    }

    // 次へボタン押下
    async clickNextPageButton() {
        await this.nextPage.click();
    }

    // 前へボタン押下
    async seePrevPageButton() {
        await expect(this.prevPage).toBeVisible();
    }

    // 登録完了メッセージ
    async seeSavedMessage() {
        await expect(this.page.locator('.alert-success')).toContainText('保存しました');
    }

    // 定休日レコード作成
    async createCalendar(
        record: number,
    ) {
        for (let i = 0; i &lt; record; i++) {
            await createCalendar();
        }
    }
}</code></pre>



<h4 class="wp-block-heading">(3) 【type】ECCUBEから返ってきてほしいリスポンスの期待型</h4>



<p>《場所》<br>e2e-tests/types/calendar.type.ts</p>



<pre class="wp-block-code"><code>export type Calendar = {
    "id": number,
    "title": string,
    "holiday": string,
    "create_date": string,
    "update_date": string,
    "baseInfo": {
        "id": number
    }
}</code></pre>



<h4 class="wp-block-heading">(4)【fixtures】APIを使用</h4>



<p>《場所》<br>e2e-tests/fixtures/admin/tenant/individual_settings.fixture.ts</p>



<pre class="wp-block-code"><code>import {request} from "@playwright/test";
import {Calendar} from "../../../types/calendar.type";

/**
 * 定休日カレンダーのレコード作成
 */
// Promise&lt;typeファイル-&gt;type名&gt;
export const createCalendar = async (): Promise&lt;Calendar&gt; =&gt; {
    
    // 新規HTTPリクエストする
    const context = await request.newContext();

    // GETでURLにアクセスー＞リスポンスを返却
    // APIクッキーの作成
    await context.get(`/fixture/get_mall_role`);

    // ECCUBE側(FixtureController.php)の指定ルートにPOST依頼をかけている
    // 処理結果を変数に格納
    const CalendarResponse = await context.post('/fixture/calendar/generate_calendar');
    
    // 結果をJSONに変換
    return await CalendarResponse.json();
}</code></pre>



<h4 class="wp-block-heading">(5) 【generator】DBの操作</h4>



<p>《場所》<br>tests/Eccube/Tests/Fixture/Generator.php</p>



<pre class="wp-block-code"><code>
    /**
     * Calendar オプジェクトを生成して返す.
     * @return Calendar
     */
    public function createCalendar()
    {
        // 新規カレンダーオブジェクトを作成
        $Calendar = new Calendar();

        // カレンダーを登録したい店舗を変数に格納
        $tenant_a = 2;
        $tenant = $this-&gt;entityManager-&gt;getRepository(BaseInfo::class)-&gt;find($tenant_a);

        // レコードに値を設定し保存
        $title = '年中無休で営業しております';
        $Calendar
            -&gt;setBaseInfo($tenant)
            -&gt;setTitle($title)
            -&gt;setHoliday(new \DateTime())
            -&gt;setCreateDate(new \DateTime())
            -&gt;setUpdateDate(new \DateTime());
        $this-&gt;entityManager-&gt;persist($Calendar);
        $this-&gt;entityManager-&gt;flush();

        // 登録結果を返す
        return $Calendar;
    }</code></pre>



<h4 class="wp-block-heading">(6) 【fixture】ECCUBE側でHTTPリクエストの受け取り + レコード作成</h4>



<pre class="wp-block-code"><code>    /**
     * 定休日カレンダーの作成
     */
    // ルート名は任意
    #&#91;Route(
        '/calendar/generate_calendar',
        name: 'generate_calendar',
        methods: &#91;'POST'],
    )]
    public function generateCalendarWithClass(Request $request, bool $baseOrderOnly = true): Response
    {   
        // カレンダーレコードを作成。
        $Calendar = $this->generator->createCalendar();

        // createCalendar()の実行結果をjsonファイルとして返す。
        return new Response(
            $Calendar->toJSON(),
            Response::HTTP_CREATED,
            &#91;'Content-Type' => 'application/json']
        );
    }</code></pre>



<h2 class="wp-block-heading">関連サイト</h2>



<figure class="wp-block-embed is-type-wp-embed">
<blockquote class="wp-embedded-content" data-secret="QlyUF2eq1p"><a href="https://neko-neko.sai-net.work/722/">【ECCUBE】【Playwrite】fixtrueを使ってDBにレコードを追加する方法</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;【ECCUBE】【Playwrite】fixtrueを使ってDBにレコードを追加する方法&#8221; &#8212; ねこねこネットワーク" src="https://neko-neko.sai-net.work/722/embed/#?secret=ymqGrkjf1W#?secret=QlyUF2eq1p" data-secret="QlyUF2eq1p" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</figure>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/759/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【ECCUBE】【Playwrite】fixtrueを使ってDBにレコードを追加する方法</title>
		<link>https://neko-neko.sai-net.work/722/</link>
					<comments>https://neko-neko.sai-net.work/722/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Thu, 03 Oct 2024 10:14:22 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<category><![CDATA[テスト]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=722</guid>

					<description><![CDATA[今回は本編で苦戦した fixtrue を [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>今回は本編で苦戦した fixtrue を使ってのレコード追加方法を記していく。</p>



<p></p>



<h2 class="wp-block-heading">したい事</h2>



<p>E2E側からの操作でECCUBEのDBにレコードを追加したい。<br>今回は、dtb_calendarにレコードを追加をする。</p>



<figure class="wp-block-embed is-type-wp-embed">
<blockquote class="wp-embedded-content" data-secret="5aRKKWKyWq"><a href="https://neko-neko.sai-net.work/759/">【ECCUBE】【playwrite】店舗設定：個別設定のE2Eテストコード全体構成</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;【ECCUBE】【playwrite】店舗設定：個別設定のE2Eテストコード全体構成&#8221; &#8212; ねこねこネットワーク" src="https://neko-neko.sai-net.work/759/embed/#?secret=YF1lESlBrh#?secret=5aRKKWKyWq" data-secret="5aRKKWKyWq" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</figure>



<h2 class="wp-block-heading">実行手順</h2>



<ol class="wp-block-list">
<li>EntityManagerを使い、dtb_calendarにレコードを追加</li>



<li>ルート名の設定 + レコード作成結果を返す</li>



<li>E2E側でECCUBE側に対してのHTTPリクエスト処理を作成</li>



<li>テストコードを作成</li>
</ol>



<p></p>



<h4 class="wp-block-heading">1. EntityManagerを使い、dtb_calendarにレコードを追加</h4>



<p>《場所》<br>tests/Eccube/Tests/Fixture/Api/Controller/FixtureController.php</p>



<pre class="wp-block-code"><code>    /**
     * Calendar オプジェクトを生成して返す.
     * @return Calendar
     */
    public function createCalendar()
    {
        // 新規カレンダーオブジェクトを作成
        $Calendar = new Calendar();

        // カレンダーを登録したい店舗を変数に格納
        $tenant_a = 2;
        $tenant = $this-&gt;entityManager-&gt;getRepository(BaseInfo::class)-&gt;find($tenant_a);

        // レコードに値を設定し保存
        $title = '年中無休で営業しております';
        $Calendar
            -&gt;setBaseInfo($tenant)
            -&gt;setTitle($title)
            -&gt;setHoliday(new \DateTime())
            -&gt;setCreateDate(new \DateTime())
            -&gt;setUpdateDate(new \DateTime());
        $this-&gt;entityManager-&gt;persist($Calendar);
        $this-&gt;entityManager-&gt;flush();

        // 登録結果を返す
        return $Calendar;
    }</code></pre>



<p>《疑問》</p>



<p>疑問：店舗情報を取得しているのはなぜか？<br>結論：レコード追加先の店舗を設定するため。</p>



<p>疑問：setBaseInfo()をEntity/Calendar.phpで探してもなかった。ではどこか？<br>結論：TenantTrait.phpに関数が存在する。</p>



<p>src/Eccube/Entity/Calendar.php</p>



<pre class="wp-block-code"><code>    class Calendar extends AbstractEntity
    {
        use Traits\TenantTrait;
　　　　 .....
    }</code></pre>



<p>src/Eccube/Entity/Traits/TenantTrait.php</p>



<pre class="wp-block-code"><code>    /**
     * テナント情報を設定する
     *
     * @param BaseInfo $baseInfo
     * @return $this
     */
    public function setBaseInfo(BaseInfo $baseInfo)
    {
        $this-&gt;baseInfo = $baseInfo;
        return $this;
    }</code></pre>



<p></p>



<h4 class="wp-block-heading">2. ルート名の設定 + レコード作成結果を返す</h4>



<p>《場所》<br>tests/Eccube/Tests/Fixture/Generator.php</p>



<pre class="wp-block-code"><code>    /**
     * 定休日カレンダーの作成
     */
    // ルート名は任意
    #&#91;Route(
        '/calendar/generate_calendar',
        name: 'generate_calendar',
        methods: &#91;'POST'],
    )]
    public function generateCalendarWithClass(Request $request, bool $baseOrderOnly = true): Response
    {   
        // レコード作成
        $Calendar = $this-&gt;generator-&gt;createCalendar();

        // createCalendar()の実行結果をJSON形式で返す
        return new Response(
            $Calendar-&gt;toJSON(),
            Response::HTTP_CREATED,
            &#91;'Content-Type' =&gt; 'application/json']
        );
    }</code></pre>



<p>#[Route]：アクセス名・期待したいるメゾット (GET? POST?)</p>



<p></p>



<h4 class="wp-block-heading">3. postmanでカレンダーレコード作成関数の実行確認</h4>



<p>（1）<a href="http://localhost:8080/fixture/get_mall_role">http://localhost:8080/fixture/get_mall_role</a> にアクセスしAPIクッキーを作成<br>（2）<a href="http://localhost:8080/fixture/calendar/generate_calendar">http://localhost:8080/fixture/calendar/generate_calendar</a> にアクセスしテストを実行</p>



<figure class="wp-block-embed is-type-wp-embed">
<blockquote class="wp-embedded-content" data-secret="0WyjT97g32"><a href="https://neko-neko.sai-net.work/742/">【ECCUBE】【POSTMAN】PostManを使いリクエストを実行</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;【ECCUBE】【POSTMAN】PostManを使いリクエストを実行&#8221; &#8212; ねこねこネットワーク" src="https://neko-neko.sai-net.work/742/embed/#?secret=T4wJFVEiFJ#?secret=0WyjT97g32" data-secret="0WyjT97g32" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</figure>



<p></p>



<h4 class="wp-block-heading">4. E2E側でECCUBE側に対してHTTPリクエストする処理を作成</h4>



<p>《場所》<br>e2e-tests/fixtures/admin/tenant/individual_settings.fixture.ts</p>



<pre class="wp-block-code"><code>/**
 * 定休日カレンダーのレコード作成
 */
// Promise&lt;typeファイル-&gt;type名&gt;
export const createCalendar = async (): Promise&lt;Calendar&gt; =&gt; {
    
    // 新規HTTPリクエストする
    const context = await request.newContext();

    // GETでURLにアクセスー＞リスポンスを返却
    // APIクッキーの作成
    await context.get(`/fixture/get_mall_role`);

    // ECCUBE側(FixtureController.php)の指定ルートにPOST依頼をかけている
    // 処理結果を変数に格納
    const CalendarResponse = await context.post('/fixture/calendar/generate_calendar');
    
    // 結果をJSONに変換
    return await CalendarResponse.json();
}</code></pre>



<p></p>



<h4 class="wp-block-heading">5. テストコードを作成</h4>



<p>《場所》<br>e2e-tests/spec/admin/tenant/individual_settings.spec.ts</p>



<pre class="wp-block-code"><code>test('定休日カレンダー設定_複数行_ページ遷移確認',
    {tag: &#91;"@tenant_owner_a"]},
    async ({loginPage,page}) =&gt; {
　　　　 // レコード
        const ShopIndividualSettingsPage = new AdminShopIndividualSettingsPage(page);

　　　　　......
　　　　　
        // 10行のカレンダー作成
        await ShopIndividualSettingsPage.createCalendar(10);
    }
);</code></pre>



<p>《場所》<br>e2e-tests/pages/admin/tenant/individual_settings.page.ts</p>



<pre class="wp-block-code"><code>export class AdminShopIndividualSettingsPage {

    // 定休日レコード作成
    async createCalendar(
        record: number,
    ) {
        for (let i = 0; i &lt; record; i++) {
            await createCalendar();
        }
    }
}</code></pre>



<p></p>



<h2 class="wp-block-heading">E2Eテストの実行</h2>



<p>リスポンス情報と共に&#8221;1 passed (5.0s)&#8221;が返却されたため成功！！(^▽^)/</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="177" src="https://neko-neko.sai-net.work/cms/wp-content/uploads/2024/10/スクリーンショット-2024-10-03-200734-1024x177.jpg" alt="" class="wp-image-733" srcset="https://neko-neko.sai-net.work/cms/wp-content/uploads/2024/10/スクリーンショット-2024-10-03-200734-1024x177.jpg 1024w, https://neko-neko.sai-net.work/cms/wp-content/uploads/2024/10/スクリーンショット-2024-10-03-200734-300x52.jpg 300w, https://neko-neko.sai-net.work/cms/wp-content/uploads/2024/10/スクリーンショット-2024-10-03-200734-768x132.jpg 768w, https://neko-neko.sai-net.work/cms/wp-content/uploads/2024/10/スクリーンショット-2024-10-03-200734-1536x265.jpg 1536w, https://neko-neko.sai-net.work/cms/wp-content/uploads/2024/10/スクリーンショット-2024-10-03-200734-2048x353.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-embed is-type-wp-embed">
<blockquote class="wp-embedded-content" data-secret="rpzVgvxz4x"><a href="https://neko-neko.sai-net.work/587/">【EC-CUBE】【Playlight】E2Eテストを実行</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;【EC-CUBE】【Playlight】E2Eテストを実行&#8221; &#8212; ねこねこネットワーク" src="https://neko-neko.sai-net.work/587/embed/#?secret=m8hydnRM4y#?secret=rpzVgvxz4x" data-secret="rpzVgvxz4x" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</figure>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/722/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【ECCUBE】【Playwrite】テストコードを作成する</title>
		<link>https://neko-neko.sai-net.work/682/</link>
					<comments>https://neko-neko.sai-net.work/682/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Wed, 25 Sep 2024 10:11:52 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<category><![CDATA[テスト]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=682</guid>

					<description><![CDATA[したい事 実際のコード 1. 会員情報の [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">したい事</h2>



<ol class="wp-block-list">
<li>会員情報の登録確認</li>



<li>画面遷移とテキスト表示確認</li>



<li>管理側 -&gt; コンテンツ管理 -&gt; ファイル管理 -&gt; htmlファイルのダウンロード実行確認</li>
</ol>



<p></p>



<h2 class="wp-block-heading">実際のコード</h2>



<h4 class="wp-block-heading">1. 会員情報の登録確認</h4>



<p>フロント側 -&gt; 新規会員登録 -&gt; 趣味項目を追加し、DBへの登録確認</p>



<p>(1) 下記に従い、新規会員登録画面に新規入力項目を追加</p>



<figure class="wp-block-embed is-type-wp-embed">
<blockquote class="wp-embedded-content" data-secret="Km0eo0tEER"><a href="https://neko-neko.sai-net.work/92/">【EC-CUBE】【Front】新規会員登録画面に新規入力項目を追加</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;【EC-CUBE】【Front】新規会員登録画面に新規入力項目を追加&#8221; &#8212; ねこねこネットワーク" src="https://neko-neko.sai-net.work/92/embed/#?secret=xxwgwDjcc9#?secret=Km0eo0tEER" data-secret="Km0eo0tEER" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</figure>



<p>(2) テストコードを記述</p>



<p>EntryPageクラス<br>場所：e2e-tests/pages/front/entry.page.ts</p>



<pre class="wp-block-code"><code>// 外部ライブラリからlocatorとpageクラスをimport
import {Locator, Page} from "@playwright/test";

export class EntryPage {
　　// 読み込み専用の変数設定 
    readonly page: Page;
    readonly url: string;
    readonly termsLink: Locator;

　　// 変数に値を格納
    constructor(page: Page) {
        // 上記で設定した変数に↓が格納
　　　　 // playrightのpageオブジェクト
        this.page = page;
　　　　　// テスト対象のurl
        this.url = `/entry`;
        this.termsLink = page.locator('.ec-checkbox .ec-link');
    }
　　
　　// 遷移関数
    async goto() {
        await this.page.goto(this.url);
    }

　　// 指定リンクを押下
    async clickServiceTermsLink() {
        await this.termsLink.click();
    }
}</code></pre>



<p>テスト実行関数<br>場所：e2e-tests/spec/front/entry.spec.ts</p>



<pre class="wp-block-code"><code>// クラスの使用宣言
import {expect, test} from "@playwright/test";
import {EntryPage} from "../../pages/front/entry.page";

test('ECCUBE 新規会員登録チェック', async ({ page }) =&gt; {
    // 変数設定
    const entryPage = new EntryPage(page);
    const name01 = 'テスト';
    const name02 = '太郎';
    const kana01 = 'テスト';
    const kana02 = 'タロウ';
    const hobby = '趣味';
    const pref = '27';
    const add_num = '5400010';
    const add01 = '大阪府中央区';
    const add02 = 'ドエル南本町';
    const phone_num = '11122223333';
    const email01 = 'testtaro@gmail.com';
    const email02 = 'testtaro@gmail.com';
    const pass01 = 'sainetJp5018+++---';
    const pass02 = 'sainetJp5018+++---';

    // 新規会員登録画面に遷移
    await entryPage.goto();
　　
    // 対象(idで指定)の入力項目に値を入力
    await page.locator('#entry_name_name01').fill(name01);
    await page.locator('#entry_name_name02').fill(name02);
    await page.locator('#entry_kana_kana01').fill(kana01);
    await page.locator('#entry_kana_kana02').fill(kana02);
    await page.locator('#entry_postal_code').fill(add_num);
    await page.locator('#entry_address_pref').selectOption(pref);
    await page.locator('#entry_hobby').fill(hobby);
    await page.locator('#entry_address_addr01').fill(add01);
    await page.locator('#entry_address_addr02').fill(add02);
    await page.locator('#entry_phone_number').fill(phone_num);
    await page.locator('#entry_email_first').fill(email01);
    await page.locator('#entry_email_second').fill(email02);
    await page.locator('#entry_plain_password_first').fill(pass01);
    await page.locator('#entry_plain_password_second').fill(pass02);
    await page.locator('#entry_user_policy_check').click();
　　
　　// name："指定テキストが入る" という名前のボタン要素を押下
    await page.getByRole('button', { name: '同意する' }).click();
    await page.getByRole('button', { name: '会員登録をする' }).click();
   
　　// 完了画面の表示確認
　　await expect(page).toHaveURL('/entry/complete');
});</code></pre>



<p></p>



<h4 class="wp-block-heading">2. 画面遷移とテキスト表示確認</h4>



<p>フロント側 -&gt; Mypage -&gt; 趣味項目を追加し、指定のページまで画面遷移とテキスト表示確認</p>



<p>(1) 下記に従い、MyPageに趣味項目を追加</p>



<p>(2) テストコードを記述</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/682/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【ECCUBE】【Playwrite】ファイル構成とコードの流れ</title>
		<link>https://neko-neko.sai-net.work/670/</link>
					<comments>https://neko-neko.sai-net.work/670/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Wed, 25 Sep 2024 09:11:56 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<category><![CDATA[テスト]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=670</guid>

					<description><![CDATA[ファイル構成 config：eccube [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">ファイル構成</h2>



<p>config：eccubeへの接続情報が記載 (URLやログイン情報)<br>fixtures：テスト実行事前準備ファイル格納 <br>(ECCUBEにログインしたり、受注情報を登録したりする)<br>(fixturesがないと、ECCUBEにアクセスできない)<br>pages：specで使う関数・クラスまとめ<br>spec：テストコード格納<br>type：</p>



<h2 class="wp-block-heading">コード理解</h2>



<p>場所：e2e-tests/spec/admin/order/order/list.spec.ts<br>関数：EA0401-UC03-T01 配送CSVダウンロード</p>



<p>ここでは、from 以降のパスでexportされているクラスや、定数を取得(import)している。</p>



<pre class="wp-block-code"><code>import {expect, test} from "../../../../fixtures/admin_login.fixture";
import {Order_count} from "../../../../types/order_count.type";
import {createOrder, hasExistingOrders} from "../../../../fixtures/admin/order/order.fixture";
import {AdminOrderListPage} from "../../../../pages/admin/order/order/list.page";
import {Download} from "@playwright/test";
import {Iconv} from "iconv";</code></pre>



<p></p>



<p>EA0401-UC03-T01 配送CSVダウンロード</p>



<pre class="wp-block-code"><code>test('EA0401-UC03-T01 配送CSVダウンロード', async ({ loginPage, page }) =&gt; {
    // ログイン実行がされたか確認
    await loginPage.seeAfterLoginSuccess();
    // 受注数を数えている？？
    const existingOrdersCnt: Order_count = await hasExistingOrders();
    // 対象のid要素を取得
    const OrderList = new AdminOrderListPage(page);
    // documentをダウンロードし終えるまで待機
    await page.waitForLoadState('domcontentloaded');
    // 一覧押下
    await OrderList.gotoViaMenu();
    // 件数確認
    await OrderList.confirmTotalResultCount(existingOrdersCnt.product_count);
    // ダウンロードが開始されるまで待機
    const downloadPromise = page.waitForEvent('download', { timeout: 2000});
    // csvボタン -&gt; 出荷・受注CSVが表示されるか確認
    await OrderList.downloadOrderDeliveryCsv();
    // イベント実行されたか確認
    const download: Download = await downloadPromise;
    // assert filename
    // ダウンロードしたファイルとが、指定のファイル名と一致するか確認
    expect(download.suggestedFilename()).toMatch(new RegExp('^shipping_\\d{14}\\.csv$'));
    // get and assert stats
    const fs = require('fs').promises;
    //　疑問：何している？
    expect((await fs.stat(await download.path() as string)).size).toBeGreaterThan(200);
    
    const path: string = await download.path();
    const content: string = await fs.readFile(path);
    const iconv = new Iconv('SHIFT_JIS', 'UTF-8');
    const utf8Content = iconv.convert(content).toString();
    const rows = utf8Content.trim().split('\n');
    const rowCount = rows.length;
    expect(rowCount).toBeGreaterThan(existingOrdersCnt.product_count + 1);
});</code></pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/670/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【ECCUBE】【Twig】Block 要素の編集・追加方法</title>
		<link>https://neko-neko.sai-net.work/664/</link>
					<comments>https://neko-neko.sai-net.work/664/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Wed, 25 Sep 2024 03:50:10 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=664</guid>

					<description><![CDATA[したい事 MYページに追加した「趣味項目 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">したい事</h2>



<p>MYページに追加した「趣味項目」にアクセスした際に、ECCUEUの店舗名、カテゴリを表示したい。</p>



<p>hobby.twig</p>



<pre class="wp-block-code"><code>{% block main %}</code></pre>



<h2 class="wp-block-heading">追加方法</h2>



<p>管理画面 -> コンテンツ管理 -> ページ管理とレイアウト管理を追加</p>



<h2 class="wp-block-heading">参考サイト</h2>



<figure class="wp-block-embed">https://cyberspace-jp.com/2022/1462</figure>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/664/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【ECCUBE】【フロント】header の表示名を追加・変更</title>
		<link>https://neko-neko.sai-net.work/653/</link>
					<comments>https://neko-neko.sai-net.work/653/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Wed, 25 Sep 2024 02:46:52 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=653</guid>

					<description><![CDATA[概要 下記ディレクトリには、DBに登録さ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">概要</h2>



<p>下記ディレクトリには、DBに登録されていない表示文言が設定されている。</p>



<pre class="wp-block-code"><code>場所：src/Eccube/Resource/locale/messages.ja.yaml</code></pre>



<p></p>



<h2 class="wp-block-heading">変更方法</h2>



<h4 class="wp-block-heading">(例) フロント -> mypage -> (ヘッダ) &#8220;お気に入り一覧&#8221; を変更する場合</h4>



<p>messages.ja.yaml</p>



<pre class="wp-block-code"><code>#------------------------------------------------------------------------------------
# マイページ
#------------------------------------------------------------------------------------
front.mypage.nav__favorite: お気に入り一覧 &lt;= この文字列を変更するとフロント画面に反映されるよ</code></pre>



<p>src/Eccube/Resource/template/default/Mypage/favorite.twig</p>



<pre class="wp-block-code"><code> &lt;div class="ec-pageHeader">
     &lt;h1>{{ 'front.mypage.title'|trans }}/{{ 'front.mypage.nav__favorite'|trans }}&lt;/h1>
 &lt;/div></code></pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/653/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【EC-CUBE】【Playlight】E2Eテストを実行</title>
		<link>https://neko-neko.sai-net.work/587/</link>
					<comments>https://neko-neko.sai-net.work/587/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Tue, 24 Sep 2024 05:28:41 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<category><![CDATA[エラー]]></category>
		<category><![CDATA[環境構築]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=587</guid>

					<description><![CDATA[前提 実行手順 2. playwrite [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">前提</h2>



<ul class="wp-block-list">
<li>EC-CUBE Enterprise版 がローカルに保存されている</li>
</ul>



<p></p>



<h2 class="wp-block-heading">実行手順</h2>



<ol class="wp-block-list">
<li> EC-CUBE Enterprise版 コンテナ を起動</li>
</ol>



<pre class="wp-block-code"><code>docker compose -f docker-compose.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml up -d</code></pre>



<p>  2. playwriteを起動</p>



<pre class="wp-block-code"><code>全体テスト
dev/run_docker_playwright.sh

特定テスト
dev/run_docker_playwright.sh -g テスト名</code></pre>



<p>  3. 実行結果を確認<br>　確認場所：./output/playwright-report/index.html</p>



<pre class="wp-block-code"><code>php -S 127.0.0.1:8081 -t ./output/playwright-report</code></pre>



<p>=> ブラウザで127.0.0.1:8081にアクセスすれば出力レポートが見えるよ！！</p>



<p>見れない場合&#8230; </p>



<p>ポートが空いておらずアクセスできない可能性があるため、</p>



<pre class="wp-block-code"><code>127.0.0.1:8081 -> 127.0.0.1:8082</code></pre>



<p>に変更し、再度コマンド実行</p>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/587/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【EC-CUBE】【E2Eテスト】E2E(codeception)のテストコード理解</title>
		<link>https://neko-neko.sai-net.work/570/</link>
					<comments>https://neko-neko.sai-net.work/570/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Fri, 20 Sep 2024 13:18:27 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=570</guid>

					<description><![CDATA[対象 EC-CUBE enterpris [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">対象</h2>



<p>EC-CUBE enterprise版 -&gt; (front) 新規会員登録の入力から登録完了まで</p>



<p>URL：/Entry<br>関数名：customer_会員登録正常<br>ファイル場所：codeception/acceptance/EF04CustomerCest.php</p>



<h2 class="wp-block-heading">コード</h2>



<pre class="wp-block-code has-small-font-size"><code>    public function customer_会員登録正常(AcceptanceTester $I)
    {
        $I-&gt;wantTo('EF0401-UC01-T01 会員登録 正常パターン');
        $I-&gt;getScenario()-&gt;incomplete('element click intercepted: Element is not clickable at point (952, 1599) が発生するため、一旦未実装とします');
        $I-&gt;amOnPage('/entry');
        // 疑問:Fixturesとはテストを実行するための基礎情報を作成するためのクラス
        $faker = Fixtures::get('faker');
        $BaseInfo = Fixtures::get('baseinfo');
        $new_email = microtime(true).'.'.$faker-&gt;safeEmail;

        // 会員情報入力フォームに、会員情報を入力する
        //「同意する」ボタンを押下する
        $form = &#91;
            'entry&#91;name]&#91;name01]' =&gt; '姓',
            'entry&#91;name]&#91;name02]' =&gt; '名',
            'entry&#91;kana]&#91;kana01]' =&gt; 'セイ',
            'entry&#91;kana]&#91;kana02]' =&gt; 'メイ',
            'entry&#91;postal_code]' =&gt; '530-0001',
            'entry&#91;address]&#91;pref]' =&gt; &#91;'value' =&gt; '27'],
            'entry&#91;address]&#91;addr01]' =&gt; '大阪市北区',
            'entry&#91;address]&#91;addr02]' =&gt; '梅田2-4-9 ブリーゼタワー13F',
            'entry&#91;phone_number]' =&gt; '111-111-111',
            'entry&#91;email]&#91;first]' =&gt; $new_email,
            'entry&#91;email]&#91;second]' =&gt; $new_email,
            'entry&#91;plain_password]&#91;first]' =&gt; 'password1234',
            'entry&#91;plain_password]&#91;second]' =&gt; 'password1234',
            'entry&#91;job]' =&gt; &#91;'value' =&gt; '1'],
            'entry&#91;user_policy_check]' =&gt; '1',
        ];

        $findPluginByCode = Fixtures::get('findPluginByCode');
        $Plugin = $findPluginByCode('MailMagazine42');
        if ($Plugin) {
            $I-&gt;amGoingTo('メルマガプラグインを発見したため、メルマガを購読します');
            $form&#91;'entry&#91;mailmaga_flg]'] = '1';
        }
        // 疑問：controllerにFormを投げている？
        $I-&gt;submitForm(&#91;'css' =&gt; '.ec-layoutRole__main form'], $form, &#91;'css' =&gt; 'button.ec-blockBtn--action']);

        // 疑問：確認画面？
        // 入力した会員情報を確認する。
        $I-&gt;see('姓 名', '.ec-registerRole form .ec-borderedDefs dl:nth-child(1) dd');
        $I-&gt;see('111111111', '.ec-registerRole form .ec-borderedDefs dl:nth-child(5) dd');
        $I-&gt;see($new_email, '.ec-registerRole form .ec-borderedDefs dl:nth-child(6) dd');
        
        // 疑問：なぜリセットしてる？
        $I-&gt;resetEmails();

        // 「会員登録をする」ボタンを押下する
        $I-&gt;click('.ec-registerRole form button.ec-blockBtn--action');

        // 顧客に届くメール内容の確認
        $message = $I-&gt;lastMessage();
        $I-&gt;assertCount(2, $message-&gt;getRecipients(), 'Bcc で管理者にも送信するので宛先アドレスは2つ');
        $I-&gt;seeEmailCount(1);
        // 疑問：firstメールアドレスに送信されたメール内容に、指定した文字が表示されているか確認している？
        foreach (&#91;$new_email, $BaseInfo-&gt;getEmail01()] as $email) {
            $I-&gt;seeInLastEmailSubjectTo($email, '会員登録のご確認');
            $I-&gt;seeInLastEmailTo($email, '姓 名 様');
            $I-&gt;seeInLastEmailTo($email, 'この度は会員登録依頼をいただきまして、有り難うございます。');
        }

        // 「トップページへ」ボタンを押下する
        $I-&gt;click('a.ec-blockBtn--cancel');
        $I-&gt;see('新着情報', '.ec-secHeading__ja');

        // アクティベートURL取得
        $activateUrl = $I-&gt;grabFromLastEmailTo($new_email, '@/entry/activate/(.*)@');
        $I-&gt;resetEmails();

        // アクティベートURLからトップページへ
        $I-&gt;amOnPage($activateUrl);
        $I-&gt;see('新規会員登録(完了)', 'div.ec-pageHeader h1');

        // 疑問：↓は何の関数？処理最後に送るメールの事？
        $message = $I-&gt;lastMessage();
        // メールを受取り者が2人いるか確認
        $I-&gt;assertCount(2, $message-&gt;getRecipients(), 'Bcc で管理者にも送信するので宛先アドレスは2つ');
        
        // 顧客に送ったメールが1つか確認
        $I-&gt;seeEmailCount(1);
        foreach (&#91;$new_email, $BaseInfo-&gt;getEmail01()] as $email) {
            $I-&gt;seeInLastEmailSubjectTo($email, '会員登録が完了しました。');
            $I-&gt;seeInLastEmailTo($email, '姓 名 様');
            $I-&gt;seeInLastEmailTo($email, '本会員登録が完了いたしました。');
        }

        $I-&gt;click('div.ec-registerCompleteRole a.ec-blockBtn--cancel');
        $I-&gt;see('新着情報', '.ec-secHeading__ja');
    }
</code></pre>



<p></p>



<h4 class="wp-block-heading">１.テスト準備</h4>



<pre class="wp-block-code"><code>        $I-&gt;wantTo('EF0401-UC01-T01 会員登録 正常パターン');
        $I-&gt;getScenario()-&gt;incomplete('element click intercepted: Element is not clickable at point (952, 1599) が発生するため、一旦未実装とします');
        $I-&gt;amOnPage('/entry');
        // 疑問:Fixturesとはテストを実行するための基礎情報を作成するためのクラス</code></pre>



<pre class="wp-block-code"><code>        $faker = Fixtures::get('faker');
        $BaseInfo = Fixtures::get('baseinfo');
        $new_email = microtime(true).'.'.$faker-&gt;safeEmail;</code></pre>



<ol class="wp-block-list">
<li>テスト準備</li>



<li>会員情報入力フォームの作成・送信</li>



<li>確認画面で入力情報の確認・登録実行</li>



<li>仮登録メールの送信確認</li>



<li>本会員完了画面の表示確認</li>



<li>本会員メールの送信確認<br>となっている事がわかった。</li>
</ol>



<h2 class="wp-block-heading">疑問</h2>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/570/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【EC-CUBE】【PHPUnit】単体テスト実行手順</title>
		<link>https://neko-neko.sai-net.work/566/</link>
					<comments>https://neko-neko.sai-net.work/566/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Fri, 20 Sep 2024 13:07:52 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<category><![CDATA[エラー]]></category>
		<category><![CDATA[環境構築]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=566</guid>

					<description><![CDATA[前提条件 概要 今回は、標準EC-CUB [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">前提条件</h2>



<ul class="wp-block-list">
<li>EC-CUBE(今回は4)プロジェクト がローカル環境に保存されている事</li>



<li>Docker でEC-CUBEを立ち上げている状態</li>



<li>OS：Ubuntu</li>
</ul>



<h2 class="wp-block-heading">概要</h2>



<p>今回は、標準EC-CUBEの単体テストをするために<br>・標準EC-CUBEの(Front)新規会員登録画面に新規入力項目を追加<br>・testファイルの書換え<br>・PHPUnit の実行 <br>という手順を踏んだ。</p>



<h2 class="wp-block-heading">実行手順</h2>



<h4 class="wp-block-heading">新規会員登録画面に新規入力項目を追加</h4>



<ol class="wp-block-list">
<li>関連テーブルに新規カラム追加<br>対象テーブル：dtb_customer<br>カラム名：hobby<br>※company_nameを参考にしながら実行</li>



<li>CustomerEntity にメンバ変数 + geter + seterを追加</li>



<li>EntryType クラス に hobbyバリデーション設定を追加</li>



<li>Twigに新規項目を追加</li>



<li>テストファイルに、新規追加項目のテスト内容を記述</li>
</ol>



<p>プロキシ―ファイルの罠話を追加<br>EntryController.php で $form = $builder->getForm(); が実行されたタイミングで<br>下記エラーが出力される。それはなぜ？<br>Can&#8217;t get a way to read the property &#8220;hobby&#8221; in class &#8220;Eccube\Entity\Customer&#8221;.<br><br>想定できる原因<br>1.（2）の設定が出来ていないのでは？<br>2.（1）でdtb_customer にカラム追加ができていないのでは？<br>=> どちらもOKだった。<br><br>customerプロキシ―ファイルをec-cubeが見ていたから。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/566/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【エラー】EC-CUBEでE2E (codeception) テストで出たエラー</title>
		<link>https://neko-neko.sai-net.work/515/</link>
					<comments>https://neko-neko.sai-net.work/515/#respond</comments>
		
		<dc:creator><![CDATA[nekoneko_admin]]></dc:creator>
		<pubDate>Fri, 20 Sep 2024 11:57:29 +0000</pubDate>
				<category><![CDATA[EC-CUBE]]></category>
		<category><![CDATA[エラー]]></category>
		<category><![CDATA[環境構築]]></category>
		<guid isPermaLink="false">https://neko-neko.sai-net.work/?p=515</guid>

					<description><![CDATA[前提条件 エラー内容 1. .shファイ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">前提条件</h2>



<ul class="wp-block-list">
<li>Ubuntu に EC-CUBEプロジェクトが存在する事</li>



<li>「EC-CUBEで E2Eテスト(cedeception) を実行」ブログを確認している事</li>
</ul>



<figure class="wp-block-embed is-type-wp-embed">
<blockquote class="wp-embedded-content" data-secret="b5fkF9uplX"><a href="https://neko-neko.sai-net.work/511/">EC-CUBEで E2Eテスト(cedeception) を実行</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;EC-CUBEで E2Eテスト(cedeception) を実行&#8221; &#8212; ねこねこネットワーク" src="https://neko-neko.sai-net.work/511/embed/#?secret=liLWSo7uWI#?secret=b5fkF9uplX" data-secret="b5fkF9uplX" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</figure>



<h2 class="wp-block-heading">エラー内容</h2>



<h4 class="wp-block-heading">1. .shファイル の アクセス権限ない問題</h4>



<p>対象ファイル：Docker ~/usr/local/bin/docker-codeception-entrypoint. sh</p>



<p><strong>エラー詳細</strong></p>



<pre class="wp-block-code"><code>failed to create shim task: OCi runtime create failed: run create failed: unable to start container process: <strong>exec:/us/local/bin/docker-codeception-entrypoint. sh": permission denied: unknown</strong></code></pre>



<p><strong>意味</strong><br>docker-codeception-entrypoint.sh のアクセス権限がない事で起こる</p>



<p><strong>出力タイミング</strong><br>codeception コンテナを作成すべく docker compose を実行した時</p>



<p><strong>解決方法</strong><br>下記コマンドで権限の付与を実行</p>



<p>場所：Ubuntu ~\dockerbuild\codeception\ココ</p>



<pre class="wp-block-code"><code>sudo chmod -x docker-codeception-entrypoint.sh
sudo chmod -R 777 docker-codeception-entrypoint.sh</code></pre>



<p></p>



<h4 class="wp-block-heading">２. .env not found</h4>



<p>対象ファイル：Docker ~/var/www/html/.env</p>



<p><strong>エラー詳細</strong></p>



<pre class="wp-block-code"><code>in ParamsLoader.php
Params file /var/www/html/.env not found</code></pre>



<p><strong>意味</strong><br>ParamsLoader.phpで参照としている&#8221;.env&#8221; が &#8220;/var/www/html/&#8221; がない事で起こるエラー</p>



<h6 class="wp-block-heading">出力タイミング</h6>



<p>1.のエラーがなくなり、再度 docker compose コマンドを実行したタイミング</p>



<p><strong>解決方法</strong><br>.env.dist ファイルをコピペし、名前を.env に変更し保存</p>



<h1 class="wp-block-heading">参考サイト</h1>



<p></p>



<p></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://neko-neko.sai-net.work/515/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
